[Mesa-dev] [PATCH] mesa-demos: Add blinking-teapot demo.
Brian Paul
brianp at vmware.com
Mon Nov 14 07:11:06 PST 2011
On 11/12/2011 04:49 PM, vlj wrote:
> blinking-teapot is an UBO demo.
> ---
> src/glsl/CMakeLists.txt | 1 +
> src/glsl/Makefile.am | 2 +
> src/glsl/blinking-teapot.c | 233 ++++++++++++++++++++++++++++++++++++++++++++
> src/glsl/shader.frag | 31 ++++++
> src/glsl/shader.vert | 16 +++
> 5 files changed, 283 insertions(+), 0 deletions(-)
> create mode 100644 src/glsl/blinking-teapot.c
> create mode 100644 src/glsl/shader.frag
> create mode 100644 src/glsl/shader.vert
>
> diff --git a/src/glsl/CMakeLists.txt b/src/glsl/CMakeLists.txt
> index 11f8e37..aeaf526 100644
> --- a/src/glsl/CMakeLists.txt
> +++ b/src/glsl/CMakeLists.txt
> @@ -24,6 +24,7 @@ set (targets
> bitmap
> brick
> bump
> + blinking-teapot
> convolutions
> deriv
> fragcoord
> diff --git a/src/glsl/Makefile.am b/src/glsl/Makefile.am
> index 5a9a802..d9b6f9b 100644
> --- a/src/glsl/Makefile.am
> +++ b/src/glsl/Makefile.am
> @@ -37,6 +37,7 @@ bin_PROGRAMS = \
> bitmap \
> brick \
> bump \
> + blinking-teapot \
> convolutions \
> deriv \
> fragcoord \
> @@ -77,6 +78,7 @@ bitmap_LDADD = ../util/libutil.la
> bezier_LDADD = ../util/libutil.la
> brick_LDADD = ../util/libutil.la
> bump_LDADD = ../util/libutil.la
> +blinking_teapot_LDADD = ../util/libutil.la
> convolutions_LDADD = ../util/libutil.la
> deriv_LDADD = ../util/libutil.la
> geom_sprites_LDADD = ../util/libutil.la
> diff --git a/src/glsl/blinking-teapot.c b/src/glsl/blinking-teapot.c
> new file mode 100644
> index 0000000..c7f0319
> --- /dev/null
> +++ b/src/glsl/blinking-teapot.c
> @@ -0,0 +1,233 @@
> +/**
> + * blinking-teapot demo. It displays a teapot whose color go from blue to pink.
> + * The color variation is handled by uniform buffer object.
> + * Sources mostly from http://www.jotschi.de/?p=427 which uses UBO SPEC example
> + *
> + * Vincent Lejeune 2011
> + */
> +
> +#include<stdio.h>
> +#include<stdlib.h>
> +#include<string.h>
> +#define GL_GLEXT_PROTOTYPES 1
> +#define GLX_GLXEXT_PROTOTYPES 1
> +#include<GL/gl.h>
> +#include<GL/freeglut.h>
> +#include<GL/glx.h>
> +#include<GL/glext.h>
It would be best to use glew (#include <GL/glew.h>) instead of
directly using glext.h
> +
> +#include<malloc.h>
> +#include<fcntl.h>
> +#include<string.h>
> +#include<sys/types.h>
> +#include<unistd.h>
Are all those unix headers needed? It would be nice if the program
would run on Windows too.
> +
> +
> +char *textFileRead(char *fn) {
> +
> +
> + FILE *fp;
> + char *content = NULL;
> +
> + int f,count;
> + f = open(fn, O_RDONLY);
> +
> + count = lseek(f, 0, SEEK_END);
> +
> + close(f);
> +
> + if (fn != NULL) {
> + fp = fopen(fn,"rt");
> +
> + if (fp != NULL) {
> +
> +
> + if (count> 0) {
> + content = (char *)malloc(sizeof(char) * (count+1));
> + count = fread(content,sizeof(char),count,fp);
> + content[count] = '\0';
> + }
> + fclose(fp);
> + }
> + }
> + return content;
> +}
There's a lot of extraneous whitespace in that function and the
indentation isn't consistent with the rest of the code. Maybe just
run 'indent' on the whole thing.
> +
> +char *VertexShaderSource, *FragmentShaderSource;
> +
> +// mouse controls
Use C-style /* */ comments to avoid warnings with some compilers.
> +int mouse_old_x, mouse_old_y;
> +int mouse_buttons = 0;
> +float rotate_x = 0.0, rotate_y = 0.0;
> +float translate_z = -2.0;
> +
> +#define glError() { \
> + GLenum err = glGetError(); \
> + while (err != GL_NO_ERROR) { \
> + printf("glError: %s caught at %s:%u", \
> + (char*)gluErrorString(err), __FILE__, __LINE__); \
> + err = glGetError(); \
> + exit(-1); \
> + } \
> + }
This macro isn't used anywhere.
> +// globals
> +int initialized = 0;
> +unsigned int window_width = 640;
> +unsigned int window_height = 480;
> +
> +float delta = 0.01;
> +GLfloat wf, hf;
> +
> +//uniform names
> +const GLchar* names[] = { "SurfaceColor", "WarmColor", "CoolColor",
> + "DiffuseWarm", "DiffuseCool" };
> +static GLuint buffer_id, uniformBlockIndex, uindex, vshad_id, fshad_id, prog_id;
> +static char* vs_file = "shader.vert";
> +static char* fs_file = "shader.frag";
> +
> +GLsizei uniformBlockSize;
> +GLint singleSize;
> +GLint offset;
> +
> +GLfloat colors[] = { 0.45, 0.45, 1, 1, 0.45, 0.45, 1, 1, 0.75, 0.75, 0.75, 1,
> + 0.0, 0.0, 1.0, 1, 0.0, 1.0, 0.0, 1, };
All those vars could be declared static, and some const.
> +void reshape(int w, int h) {
> + window_width = w;
> + window_height = h;
> + wf = (GLfloat) window_width;
> + hf = (GLfloat) window_height;
> + glMatrixMode( GL_PROJECTION);
> + glLoadIdentity();
> + gluPerspective(60.0, wf / hf, 0.1, 100.0);
> +}
> +
> +static
> +void init_opengl() {
> + initialized = 1;
> + reshape(window_width, window_height);
> +
> + VertexShaderSource = textFileRead("shader.vert");
> + FragmentShaderSource = textFileRead("shader.frag");
> +
> + const char * VS = VertexShaderSource;
> + const char * FS = FragmentShaderSource;
Put all declarations before code to avoid warnings.
> +
> + vshad_id = glCreateShader(GL_VERTEX_SHADER);
> + glShaderSource(vshad_id, 1,&VS, 0);
> +
> + fshad_id = glCreateShader(GL_FRAGMENT_SHADER);
> + glShaderSource(fshad_id, 1,&FS, NULL);
> +
> + glCompileShader(vshad_id);
> + glCompileShader(fshad_id);
> +
> + prog_id = glCreateProgram();
> + glAttachShader(prog_id, vshad_id);
> + glAttachShader(prog_id, fshad_id);
> + glLinkProgram(prog_id);
> +
> + glGenBuffers(1,&buffer_id);
> +
> + glBindBuffer(GL_UNIFORM_BUFFER, buffer_id);
> + glBufferData(GL_UNIFORM_BUFFER, uniformBlockSize, NULL, GL_DYNAMIC_DRAW);
> +
> + glBindBufferBase(GL_UNIFORM_BUFFER, 0, buffer_id);
> + glUniformBlockBinding(prog_id, uniformBlockIndex, 0);
> +
> + glGetUniformIndices(prog_id, 1,&names[2],&uindex);
> +
> + glGetActiveUniformsiv(prog_id, 1,&uindex, GL_UNIFORM_OFFSET,&offset);
> + glGetActiveUniformsiv(prog_id, 1,&uindex, GL_UNIFORM_SIZE,&singleSize);
> +
> + glViewport(0, 0, window_width, window_height);
> + glBufferData(GL_UNIFORM_BUFFER, 80, colors, GL_DYNAMIC_DRAW);
> +}
> +
> +void render() {
> + glClearColor(0.0, 0.0, 0.0, 0.0);
> + glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
> + glUseProgram(prog_id);
> + glEnable( GL_DEPTH_TEST);
> +
> + glMatrixMode( GL_MODELVIEW);
> + glLoadIdentity();
> + glTranslatef(0.0, 0.0, translate_z);
> + glRotatef(rotate_x, 1.0, 0.0, 0.0);
> + glRotatef(rotate_y, 0.0, 1.0, 0.0);
> + glColor3f(1.0, 1.0, 1.0);
> +
> + glBindBuffer(GL_UNIFORM_BUFFER, buffer_id);
> + glBufferSubData(GL_UNIFORM_BUFFER, offset, 4 * singleSize,&colors[8]);
> +
> + glFrontFace( GL_CW);
> + glutSolidTeapot(0.6);
> + glFrontFace( GL_CCW);
> + glutSwapBuffers();
> + glutPostRedisplay();
> +
> + int nColor = 8;
> + colors[nColor] += delta;
> +
> + if (colors[nColor]> 1.0) {
> + delta = -0.01;
> + }
> +
> + if (colors[nColor]< 0.0) {
> + delta = +0.01;
> + }
> +
> +}
> +
> +void display() {
> + if (!initialized) {
> + init_opengl();
> + initialized = 1;
> + }
Why are you doing this check here? init_opengl() was already called
in main().
> +
> + render();
> +}
> +
> +void mouse(int button, int state, int x, int y) {
> + if (state == GLUT_DOWN) {
> + mouse_buttons |= 1<< button;
> + } else if (state == GLUT_UP) {
> + mouse_buttons = 0;
> + }
> +
> + mouse_old_x = x;
> + mouse_old_y = y;
> + glutPostRedisplay();
> +}
> +
> +void motion(int x, int y) {
> + float dx, dy;
> + dx = x - mouse_old_x;
> + dy = y - mouse_old_y;
> +
> + if (mouse_buttons& 1) {
> + rotate_x += dy * 0.2;
> + rotate_y += dx * 0.2;
> + } else if (mouse_buttons& 4) {
> + translate_z += dy * 0.01;
> + }
> +
> + mouse_old_x = x;
> + mouse_old_y = y;
> +}
> +
> +int main(int argc, char** argv) {
> + glutInit(&argc, argv);
> + glutInitWindowSize(400, 400);
> + glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
> + glutCreateWindow("UBO Example");
> + // register callbacks
> + glutDisplayFunc(display);
> + //glutKeyboardFunc( keyboard);
> + glutMouseFunc(mouse);
> + glutMotionFunc(motion);
> + init_opengl();
> + glutMainLoop();
> + return 0;
> +}
> diff --git a/src/glsl/shader.frag b/src/glsl/shader.frag
This filename is too generic. It should be something like
blinking-teapot.frag. Same thing for the vertex shader.
-Brian
More information about the mesa-dev
mailing list