OpenGL pixel shader: Difference between revisions

From Rosetta Code
Content added Content deleted
No edit summary
(+C)
Line 8: Line 8:


See also: [http://www.opengl.org/documentation/glsl/ opengl.org's gl shader language documentation], and [http://www.lighthouse3d.com/tutorials/glsl-tutorial/ lighthouse3d.com's glsl tutorial].
See also: [http://www.opengl.org/documentation/glsl/ opengl.org's gl shader language documentation], and [http://www.lighthouse3d.com/tutorials/glsl-tutorial/ lighthouse3d.com's glsl tutorial].
=={{header|C}}==
Getting a true (pseudo) random number is surprisingly tricky. The following code makes something noisy, but not at all random:
<lang c>#include <stdio.h>
#include <GL/glew.h>
#include <GL/glut.h>

float angle = 0;
void render(void)
{
glClear(GL_COLOR_BUFFER_BIT);

glLoadIdentity();
glRotatef(angle, .3, 1, 0);
glBegin(GL_TRIANGLES);
glVertex3f(-.5, -.5, 0);
glVertex3f(0, .5, 0);
glVertex3f(.5, 0, 0);
glEnd();
angle += .01;
glutSwapBuffers();
}

void set_shader()
{
GLuint ps, vs, prog;
const char *f =
"varying float x, y, z;"
"float rand(float s) { return mod(abs(s) * 7654321 + 1, 1); }"
"void main() { gl_FragColor = vec4(rand(x), rand(y), rand(z), 1); }";
const char *v =
"varying float x, y, z;"
"void main() {"
" gl_Position = ftransform();"
" x = gl_Position.x; y = gl_Position.y; z = gl_Position.z;"
" x *= z; y *= x; z += (x + y);"
"}";

vs = glCreateShader(GL_VERTEX_SHADER);
ps = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(ps, 1, &f, 0);
glShaderSource(vs, 1, &v, 0);

glCompileShader(vs);
glCompileShader(ps);

prog = glCreateProgram();
glAttachShader(prog, ps);
glAttachShader(prog, vs);

glLinkProgram(prog);
glUseProgram(prog);
}

int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowPosition(0, 0);
glutInitWindowSize(200, 200);
glutCreateWindow("Stuff");
glutIdleFunc(render);

glewInit();
if (!glewIsSupported("GL_VERSION_2_0")) {
fprintf(stderr, "GL 2.0 unsupported\n");
exit(1);
}

set_shader();
glutMainLoop();

return 0;
}</lang>

Revision as of 01:18, 29 April 2012

OpenGL pixel shader is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

Using the triangle geometry from OpenGL. But instead of using a mechanism such as glColor3d, use a pixel shader for each pixel in the triangle. The pixel shader should pick a random RGB color for each pixel. Most pixels should have colors which are different from that of most other pixels.

Optional: provide an update mechanism, to repeatedly re-render the triangle. (Possibilities include a mouse event handler, a timer event handler or an infinite loop, or even window expose events.) Shader generated color for each pixel should be different in each render.

Optional: after updating the opengl rendering target but before rendering the triangle, query the opengl implementation to determine which versions of shaders are supported by the rendering target, list the tested shaders and the available shaders and then use a supported shader.

See also: opengl.org's gl shader language documentation, and lighthouse3d.com's glsl tutorial.

C

Getting a true (pseudo) random number is surprisingly tricky. The following code makes something noisy, but not at all random: <lang c>#include <stdio.h>

  1. include <GL/glew.h>
  2. include <GL/glut.h>

float angle = 0; void render(void) { glClear(GL_COLOR_BUFFER_BIT);

glLoadIdentity(); glRotatef(angle, .3, 1, 0); glBegin(GL_TRIANGLES); glVertex3f(-.5, -.5, 0); glVertex3f(0, .5, 0); glVertex3f(.5, 0, 0); glEnd(); angle += .01; glutSwapBuffers(); }

void set_shader() { GLuint ps, vs, prog; const char *f = "varying float x, y, z;" "float rand(float s) { return mod(abs(s) * 7654321 + 1, 1); }" "void main() { gl_FragColor = vec4(rand(x), rand(y), rand(z), 1); }"; const char *v = "varying float x, y, z;" "void main() {" " gl_Position = ftransform();" " x = gl_Position.x; y = gl_Position.y; z = gl_Position.z;" " x *= z; y *= x; z += (x + y);" "}";

vs = glCreateShader(GL_VERTEX_SHADER); ps = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(ps, 1, &f, 0); glShaderSource(vs, 1, &v, 0);

glCompileShader(vs); glCompileShader(ps);

prog = glCreateProgram(); glAttachShader(prog, ps); glAttachShader(prog, vs);

glLinkProgram(prog); glUseProgram(prog); }

int main(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); glutInitWindowPosition(0, 0); glutInitWindowSize(200, 200); glutCreateWindow("Stuff"); glutIdleFunc(render);

glewInit(); if (!glewIsSupported("GL_VERSION_2_0")) { fprintf(stderr, "GL 2.0 unsupported\n"); exit(1); }

set_shader(); glutMainLoop();

return 0; }</lang>