• Advertisement
Sign in to follow this  

GLSL:how to pass values to fragment shader.

This topic is 606 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

hi

 

this is my first program in GLSL.  I found a website that can generate a mandelbrot via the fragment shader.

 

http://nuclear.mutantstargoat.com/articles/sdr_fract/

 

I am interested in generating a julia subset.  I wondered how to pass the value of c which ranged from -2.5-2.5 for x axis and -1.2 to 1.2 in y axis.

 

i had previously able to write a julia and Mandelbrot program in fixed function pipeline api but now wanted to learn about GLSL.

 

thanks in advance.

Edited by nickme

Share this post


Link to post
Share on other sites
Advertisement

In Fixed Functional pipeline, i would used two loop to output the fractals.

 

for (cx = -2.5sx = left; cx < 2.5; sx++, cx += deltaX)

      for (cy = -1.2, sy = bottom; cy < 1.2; sy++, cy += deltaY) {

          color = Julia(cx, cy);

          glTexCoord2d(color/iter, 0.0);

          glVertex2D(sx, sy);

      }

 

in GLSL, i have no clues how to pass cx, cy.

 

my fragment shader:

 

// Julia set
#version 450
uniform sampler2D tex;
uniform vec2 c;
uniform float iter;
 
void main() {
    vec2 z;
vec2 color = vec2(0.0, 0.0);
 
    z.x = 3.0 * (gl_TexCoord[0].x - 0.5);
    z.y = 2.0 * (gl_TexCoord[0].y - 0.5);
 
    int i;
    for(; color.x < iter; color.x++) {
        float x = (z.x * z.x - z.y * z.y) + c.x;
        float y = (z.y * z.x + z.x * z.y) + c.y;
 
        if((x * x + y * y) > 4.0) break;
        z.x = x;
        z.y = y;
    }
color.x = color.x / iter;
 
    gl_FragColor =texture2D(tex, color.st);
}
 

thanks

Edited by nickme

Share this post


Link to post
Share on other sites

Only recently did my first OpenGL experiments, so please don't blindly assume what I write is correct.

 

Your "uniform" variables are the way to transfer values from the program to the GPU. Afaik these are sort of constants for the GPU. You set them before you run the computation, and the GPU only reads them.

 

You need to declare the variables in the shader program like you did with "uniform vec2 c;" (A better name than "c" is probably a good idea.)

In the code, you query its location

GLint cLocation = glGetUniformLocation(program, "c");

(I always do this after selecting the shader program with "glUseProgram", not sure if this is required.)
 

You can set the value with a "glUniform*" call. There are many such functions, the one you need depends on the type of the shader variable. For "c" (a vec2) it can be

glUniform2f(cLocation, 1.0f, 2.0f);

The 1.0f, and 2.0f can be replaced by other values of course. This glUniform takes 2 reals, if you have a vector (as in an array of float) in your source code, there are also glUniform calls to transfer such arrays in one call.

 

Hope this helps. For loads of details, see http://learnopengl.com/#!Getting-started/Shaders

 

 

PS To get "code layout" in your post, select the code, and press "<>" in the toolbar.

Edited by Alberth

Share this post


Link to post
Share on other sites

hi Alberth,

 

thanks for reply.

 

I know that I can do what you said by using glUniform2f() to pass values to shader, but then I also has to use 2 forloop to pass them to shader, that defeats the purpose of using GLSL; there is no parallism at all. and that is what i am looking for:parallism

Share this post


Link to post
Share on other sites

PS To get "code layout" in your post, select the code, and press "<>" in the toolbar.

 

I do not understand what do you mean by code layout, I do not understand the context, can you elaborate?

 

thanks 

Share this post


Link to post
Share on other sites

hi Alberth,

 

thanks for reply.

 

I know that I can do what you said by using glUniform2f() to pass values to shader, but then I also has to use 2 forloop to pass them to shader, that defeats the purpose of using GLSL; there is no parallism at all. and that is what i am looking for:parallism

 

 

You don't need the loops. I wrote a post earlier but didn't click submit when I realised you were doing Julia Sets (where the c value would remain the same and thus Alberth's answer was enough). For your Julia Sets it's this bit that calculates the z value (or c if you were doing Mandelbrot):

    z.x = 3.0 * (gl_TexCoord[0].x - 0.5);
    z.y = 2.0 * (gl_TexCoord[0].y - 0.5);

Normally you would set set your c value in your loops (for Mandelbrot at least) but this isn't possible to do in a pixel shader because the pixel doesn't really know where it is. It doesn't know if it is the first pixel, the 5th, the last. It doesn't know if it is in the top row, along the left edge or any of that useful stuff you will need. Also you are not in control of any looping any more so you can't give any of those values. Fortunately what you can do is give the shader code the information it needs to be able to calculate the values itself.

 

Because of how the quad has been setup with texture coordinates, you can use those texture coordinates in the pixel shader to work out where on the quad you are. For example, the top left of the quad has texture coordinates (0, 1). In the pixel shader then you will have:

z.x = 3.0 * (gl_TexCoord[0].x - 0.5);
z.y = 2.0 * (gl_TexCoord[0].y - 0.5);

becomes:

z.x = 3.0 * (0 - 0.5) = -1.5
z.y = 2.0 * (1 - 0.5) = 1

Thus the z value for that pixel becomes -1.5, 1.

Consider what happens in the middle of the quad; the texture coordinates are 0.5, 0.5 and so:

z.x = 3.0 * (0.5 - 0.5) = 0
z.y = 2.0 * (0.5 - 0.5) = 0

z becomes 0, 0 which makes sense since that is the center.

 

So using texture coordinates (and scale, center as in the Mandelbrot version) the shader is able to calculate it's z (or c) value rather than you having to pass it for each pixel (which would be much slower since you'd have to pass it using a texture possibly).

 

For the Julia Set the 'c' value will remain the same for every pixel so Alberth's answer should be enough fot hat since you only need to do it once.

 

I think it might be of benefit to you if you read up on how shaders work and how they interpolate the output of the vertex shader for each fragment.

 

This approach does have some downsides too. It uses floats so you'll be limited to have far you can magnify your image and it also does a lot of work each frame (it is rebuilding the entire thing each time). A better approach might be to render it to a texture once and then simply show that texture each time afterwards using a basic shader.

Edited by Nanoha

Share this post


Link to post
Share on other sites

I do not understand what do you mean by code layout, I do not understand the context, can you elaborate?
Did you notice the boxes in my post that contains code lines?

 

That is "code layout" in the forum. It selects a non-proportional font (all letters are equally wide), and adds syntax colouring to the text. Blocks of code, like your shader code become more readable if you put them in a box too.

Share this post


Link to post
Share on other sites
This approach does have some downsides too. It uses floats so you'll be limited to have far you can magnify your image and it also does a lot of work each frame (it is rebuilding the entire thing each time). A better approach might be to render it to a texture once and then simply show that texture each time afterwards using a basic shader.

 

 

yes!  in my FFP program, i used GLdouble for the cx and cy, ...etc variables and I can only mag into 10 or so times before it just all be come zeros.

 

I tested the render window with the right - left and if it is less than 1.0e-13, then I will go back to the the first coord.

 

It still not working for me.  My screen just turned black after i ran it. here is the codes in my main function.  I tested it with a texture with and showed that It can access the texture, but the screen just showed a black screen. 

int main()
{
	restart_gl_log();		// starting print gl.log header
	
	if (!glfwInit()) 
		quit("start GLFW3\n", NULL);

	window = glfwCreateWindow(wsizeX, wsizeY, "Hello Julia", NULL, NULL);
	if (!window) 
		quit("open window with GLFW3\n", NULL);
	
	glfwMakeContextCurrent(window);
	/* start GLEW extension handler */
	glewExperimental = GL_TRUE;
	glewInit();

	glEnable(GL_TEXTURE_2D);
//	vs = loadShaderFromFile("vertshader.vert", GL_VERTEX_SHADER);
//	fs = loadShaderFromFile("donotin.frag", GL_FRAGMENT_SHADER);
	fs = loadShaderFromFile("Julia.frag", GL_FRAGMENT_SHADER);

	shader_programme = glCreateProgram();
//	glAttachShader(shader_programme, vs);
	glAttachShader(shader_programme, fs);
	glLinkProgram(shader_programme);
	if (!check_program_link(shader_programme, vs, fs)) {
		quit("Program shader", NULL);
	}

	fclose(file);	// close gl.log file.
	init();
	glViewport(0, 0, wsizeX, wsizeY);
	glLoadIdentity();
	glClearColor(1.0, 0.0, 0.3, 1.0);
	while (!glfwWindowShouldClose(window)) 
	{
		glEnable(GL_TEXTURE_2D);	
		glClear(GL_COLOR_BUFFER_BIT);
		glUseProgram(shader_programme);

		glActiveTexture(GL_TEXTURE0);
		glBindTexture(GL_TEXTURE_2D, palette_ID);
		glUniform1i(glGetUniformLocation(shader_programme, "tex"), 0);

		glUniform2f(glGetUniformLocation(shader_programme, "cval"), 0.74540541, 0.1130063);

		glUniform1f(glGetUniformLocation(shader_programme, "iter"), 256.0);
	
		glBindTexture(GL_TEXTURE_2D, palette_ID);
		glActiveTexture(GL_TEXTURE0);

		draw_quad();

//		drawTexturedRect(-1.2, 0.3, 1, 1, palette_ID);

		glfwPollEvents();
		glfwSwapBuffers(window);
		
		if (GLFW_PRESS == glfwGetKey(window, GLFW_KEY_ESCAPE)) {
			glfwSetWindowShouldClose(window, 1);
		}
	}

	glfwTerminate();
	return 0;
}

I changed the variable c to cval, it is not a typo.

 

thanks in advance.

Edited by nickme

Share this post


Link to post
Share on other sites

Can you post your up to date shader too? 

 

If you put this at the end of your fragment shader main function does it display your pallet?

gl_FragColor = texture2D(tex, gl_TexCoord);
Edited by Nanoha

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement