3 #define GL_GLEXT_PROTOTYPES
12 #include "shaderutil.h"
16 #define T(x) model->triangles[(x)]
19 /* glmDraw: Renders the model to the current OpenGL context using the
22 * model - initialized GLMmodel structure
23 * mode - a bitwise OR of values describing what is to be rendered.
24 * GLM_NONE - render with only vertices
25 * GLM_FLAT - render with facet normals
26 * GLM_SMOOTH - render with vertex normals
27 * GLM_TEXTURE - render with texture coords
28 * GLM_COLOR - render with colors (color material)
29 * GLM_MATERIAL - render with materials
30 * GLM_COLOR and GLM_MATERIAL should not both be specified.
31 * GLM_FLAT and GLM_SMOOTH should not both be specified.
34 glmDraw(GLMmodel
* model
, GLuint mode
)
40 assert(model
->vertices
);
42 /* do a bit of warning */
43 if (mode
& GLM_FLAT
&& !model
->facetnorms
) {
44 printf("glmDraw() warning: flat render mode requested "
45 "with no facet normals defined.\n");
48 if (mode
& GLM_SMOOTH
&& !model
->normals
) {
49 printf("glmDraw() warning: smooth render mode requested "
50 "with no normals defined.\n");
53 if (mode
& GLM_TEXTURE
&& !model
->texcoords
) {
54 printf("glmDraw() warning: texture render mode requested "
55 "with no texture coordinates defined.\n");
58 if (mode
& GLM_FLAT
&& mode
& GLM_SMOOTH
) {
59 printf("glmDraw() warning: flat render mode requested "
60 "and smooth render mode requested (using smooth).\n");
63 if (mode
& GLM_COLOR
&& !model
->materials
) {
64 printf("glmDraw() warning: color render mode requested "
65 "with no materials defined.\n");
68 if (mode
& GLM_MATERIAL
&& !model
->materials
) {
69 printf("glmDraw() warning: material render mode requested "
70 "with no materials defined.\n");
71 mode
&= ~GLM_MATERIAL
;
73 if (mode
& GLM_COLOR
&& mode
& GLM_MATERIAL
) {
74 printf("glmDraw() warning: color and material render mode requested "
75 "using only material mode\n");
79 glEnable(GL_COLOR_MATERIAL
);
80 if (mode
& GLM_MATERIAL
)
81 glDisable(GL_COLOR_MATERIAL
);
84 glTranslatef(model
->position
[0], model
->position
[1], model
->position
[2]);
86 glBegin(GL_TRIANGLES
);
87 group
= model
->groups
;
89 if (mode
& GLM_MATERIAL
) {
90 glMaterialfv(GL_FRONT_AND_BACK
, GL_AMBIENT
,
91 model
->materials
[group
->material
].ambient
);
92 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
,
93 model
->materials
[group
->material
].diffuse
);
94 glMaterialfv(GL_FRONT_AND_BACK
, GL_SPECULAR
,
95 model
->materials
[group
->material
].specular
);
96 glMaterialf(GL_FRONT_AND_BACK
, GL_SHININESS
,
97 model
->materials
[group
->material
].shininess
);
100 if (mode
& GLM_COLOR
) {
101 glColor3fv(model
->materials
[group
->material
].diffuse
);
104 for (i
= 0; i
< group
->numtriangles
; i
++) {
106 glNormal3fv(&model
->facetnorms
[3 * T(group
->triangles
[i
]).findex
]);
108 if (mode
& GLM_SMOOTH
)
109 glNormal3fv(&model
->normals
[3 * T(group
->triangles
[i
]).nindices
[0]]);
110 if (mode
& GLM_TEXTURE
)
111 glTexCoord2fv(&model
->texcoords
[2*T(group
->triangles
[i
]).tindices
[0]]);
112 glVertex3fv(&model
->vertices
[3 * T(group
->triangles
[i
]).vindices
[0]]);
115 model
->vertices
[3 * T(group
->triangles
[i
]).vindices
[0] + X
],
116 model
->vertices
[3 * T(group
->triangles
[i
]).vindices
[0] + Y
],
117 model
->vertices
[3 * T(group
->triangles
[i
]).vindices
[0] + Z
]);
120 if (mode
& GLM_SMOOTH
)
121 glNormal3fv(&model
->normals
[3 * T(group
->triangles
[i
]).nindices
[1]]);
122 if (mode
& GLM_TEXTURE
)
123 glTexCoord2fv(&model
->texcoords
[2*T(group
->triangles
[i
]).tindices
[1]]);
124 glVertex3fv(&model
->vertices
[3 * T(group
->triangles
[i
]).vindices
[1]]);
127 model
->vertices
[3 * T(group
->triangles
[i
]).vindices
[1] + X
],
128 model
->vertices
[3 * T(group
->triangles
[i
]).vindices
[1] + Y
],
129 model
->vertices
[3 * T(group
->triangles
[i
]).vindices
[1] + Z
]);
132 if (mode
& GLM_SMOOTH
)
133 glNormal3fv(&model
->normals
[3 * T(group
->triangles
[i
]).nindices
[2]]);
134 if (mode
& GLM_TEXTURE
)
135 glTexCoord2fv(&model
->texcoords
[2*T(group
->triangles
[i
]).tindices
[2]]);
136 glVertex3fv(&model
->vertices
[3 * T(group
->triangles
[i
]).vindices
[2]]);
139 model
->vertices
[3 * T(group
->triangles
[i
]).vindices
[2] + X
],
140 model
->vertices
[3 * T(group
->triangles
[i
]).vindices
[2] + Y
],
141 model
->vertices
[3 * T(group
->triangles
[i
]).vindices
[2] + Z
]);
155 glmMakeVBOs(GLMmodel
*model
)
157 uint bytes
, vertexFloats
, i
;
161 model
->posOffset
= 0;
163 if (model
->numnormals
> 0) {
164 assert(model
->numnormals
== model
->numvertices
);
165 model
->normOffset
= vertexFloats
* sizeof(GLfloat
);
169 if (model
->numtexcoords
> 0) {
170 assert(model
->numtexcoords
== model
->numvertices
);
171 model
->texOffset
= vertexFloats
* sizeof(GLfloat
);
175 model
->vertexSize
= vertexFloats
;
177 bytes
= (model
->numvertices
+ 1) * vertexFloats
* sizeof(float);
179 buffer
= (float *) malloc(bytes
);
180 for (i
= 0; i
< model
->numvertices
; i
++) {
181 /* copy vertex pos */
183 buffer
[i
* vertexFloats
+ j
++] = model
->vertices
[i
* 3 + 0];
184 buffer
[i
* vertexFloats
+ j
++] = model
->vertices
[i
* 3 + 1];
185 buffer
[i
* vertexFloats
+ j
++] = model
->vertices
[i
* 3 + 2];
186 if (model
->numnormals
> 0) {
187 buffer
[i
* vertexFloats
+ j
++] = model
->normals
[i
* 3 + 0];
188 buffer
[i
* vertexFloats
+ j
++] = model
->normals
[i
* 3 + 1];
189 buffer
[i
* vertexFloats
+ j
++] = model
->normals
[i
* 3 + 2];
191 if (model
->numtexcoords
> 0) {
192 buffer
[i
* vertexFloats
+ j
++] = model
->texcoords
[i
* 2 + 0];
193 buffer
[i
* vertexFloats
+ j
++] = model
->texcoords
[i
* 2 + 1];
197 glGenBuffersARB(1, &model
->vbo
);
198 glBindBufferARB(GL_ARRAY_BUFFER_ARB
, model
->vbo
);
199 glBufferDataARB(GL_ARRAY_BUFFER_ARB
, bytes
, buffer
, GL_STATIC_DRAW_ARB
);
200 glBindBufferARB(GL_ARRAY_BUFFER_ARB
, 0);
207 _glmLoadTexture(GLMmaterial
*mat
)
210 GLint imgWidth
, imgHeight
;
212 GLubyte
*image
= NULL
;
214 glGenTextures(1, &mat
->texture_kd
);
216 image
= LoadRGBImage( mat
->map_kd
, &imgWidth
, &imgHeight
, &imgFormat
);
218 /*fprintf(stderr, "Couldn't open texture %s\n", mat->map_kd);*/
225 printf("load texture %s %d x %d\n", mat
->map_kd
, imgWidth
, imgHeight
);
227 glBindTexture(GL_TEXTURE_2D
, mat
->texture_kd
);
228 gluBuild2DMipmaps(GL_TEXTURE_2D
, 3, imgWidth
, imgHeight
,
229 imgFormat
, GL_UNSIGNED_BYTE
, image
);
232 glTexParameteri( GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_REPEAT
);
233 glTexParameteri( GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_REPEAT
);
234 glTexParameteri( GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR_MIPMAP_LINEAR
);
235 glTexParameteri( GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
240 glmLoadTextures(GLMmodel
*model
)
244 for (i
= 0; i
< model
->nummaterials
; i
++) {
245 GLMmaterial
*mat
= &model
->materials
[i
];
246 _glmLoadTexture(mat
);
252 glmDrawVBO(GLMmodel
*model
)
258 glBindBufferARB(GL_ARRAY_BUFFER_ARB
, model
->vbo
);
260 glVertexPointer(3, GL_FLOAT
, model
->vertexSize
* sizeof(float),
261 (void *) model
->posOffset
);
262 glEnableClientState(GL_VERTEX_ARRAY
);
264 if (model
->numnormals
> 0) {
265 glNormalPointer(GL_FLOAT
, model
->vertexSize
* sizeof(float),
266 (void *) model
->normOffset
);
267 glEnableClientState(GL_NORMAL_ARRAY
);
270 if (model
->numtexcoords
> 0) {
271 glTexCoordPointer(2, GL_FLOAT
, model
->vertexSize
* sizeof(float),
272 (void *) model
->texOffset
);
273 glEnableClientState(GL_TEXTURE_COORD_ARRAY
);
277 glTranslatef(model
->position
[0], model
->position
[1], model
->position
[2]);
278 glScalef(model
->scale
, model
->scale
, model
->scale
);
280 for (group
= model
->groups
; group
; group
= group
->next
) {
281 if (group
->numtriangles
> 0) {
283 glmShaderMaterial(&model
->materials
[group
->material
]);
285 glDrawRangeElements(GL_TRIANGLES
,
286 group
->minIndex
, group
->maxIndex
,
287 3 * group
->numtriangles
,
288 GL_UNSIGNED_INT
, group
->triIndexes
);
294 glBindBufferARB(GL_ARRAY_BUFFER_ARB
, 0);
295 glDisableClientState(GL_VERTEX_ARRAY
);
296 glDisableClientState(GL_NORMAL_ARRAY
);
297 glDisableClientState(GL_TEXTURE_COORD_ARRAY
);
302 /* glmList: Generates and returns a display list for the model using
303 * the mode specified.
305 * model - initialized GLMmodel structure
306 * mode - a bitwise OR of values describing what is to be rendered.
307 * GLM_NONE - render with only vertices
308 * GLM_FLAT - render with facet normals
309 * GLM_SMOOTH - render with vertex normals
310 * GLM_TEXTURE - render with texture coords
311 * GLM_COLOR - render with colors (color material)
312 * GLM_MATERIAL - render with materials
313 * GLM_COLOR and GLM_MATERIAL should not both be specified.
314 * GLM_FLAT and GLM_SMOOTH should not both be specified.
317 glmList(GLMmodel
* model
, GLuint mode
)
321 list
= glGenLists(1);
322 glNewList(list
, GL_COMPILE
);
323 glmDraw(model
, mode
);
331 static const char *VertexShader
=
332 "varying vec3 normal; \n"
334 " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; \n"
335 " normal = gl_NormalMatrix * gl_Normal; \n"
336 " gl_TexCoord[0] = gl_MultiTexCoord0; \n"
340 * Two %s substitutions:
341 * diffuse texture? true/false
342 * specular texture? true/false
344 static const char *TexFragmentShader
=
345 "uniform vec4 ambient, diffuse, specular; \n"
346 "uniform vec4 ambientLight, diffuseLight, specularLight; \n"
347 "uniform float shininess; \n"
348 "uniform sampler2D diffTex; \n"
349 "uniform samplerCube specTex; \n"
350 "varying vec3 normal; \n"
354 " vec4 diffTerm, specTerm; \n"
355 " float dotProd = max(dot(gl_LightSource[0].position.xyz, \n"
356 " normalize(normal)), 0.0);\n"
357 " float dotProd2 = max(dot(-gl_LightSource[0].position.xyz, \n"
358 " normalize(normal)), 0.0);\n"
359 " dotProd += dotProd2; \n"
361 " diffTerm = diffuse * diffuseLight * dotProd; \n"
363 " diffTerm *= texture2D(diffTex, gl_TexCoord[0].st); \n"
365 " specTerm = specular * specularLight * pow(dotProd, shininess); \n"
367 " specTerm *= textureCube(specTex, normal); \n"
369 " gl_FragColor = ambient * ambientLight + diffTerm + specTerm; \n"
374 glmShaderMaterial(GLMmaterial
*mat
)
376 static const float ambientLight
[4] = { 0.1, 0.1, 0.1, 0.0 };
377 static const float diffuseLight
[4] = { 0.75, 0.75, 0.75, 1.0 };
378 static const float specularLight
[4] = { 1.0, 1.0, 1.0, 0.0 };
381 /* make shader now */
382 char newShader
[10000];
384 const char *diffuseTex
= mat
->texture_kd
? "true" : "false";
385 const char *specularTex
= mat
->texture_ks
? "true" : "false";
386 GLint uAmbientLight
, uDiffuseLight
, uSpecularLight
;
388 /* replace %d with 0 or 1 */
389 sprintf(newShader
, TexFragmentShader
, diffuseTex
, specularTex
);
391 printf("===== new shader =====\n%s\n============\n", newShader
);
393 vs
= CompileShaderText(GL_VERTEX_SHADER
, VertexShader
);
394 fs
= CompileShaderText(GL_FRAGMENT_SHADER
, newShader
);
395 mat
->prog
= LinkShaders(vs
, fs
);
398 glUseProgram(mat
->prog
);
400 mat
->uAmbient
= glGetUniformLocation(mat
->prog
, "ambient");
401 mat
->uDiffuse
= glGetUniformLocation(mat
->prog
, "diffuse");
402 mat
->uSpecular
= glGetUniformLocation(mat
->prog
, "specular");
403 mat
->uShininess
= glGetUniformLocation(mat
->prog
, "shininess");
404 mat
->uDiffTex
= glGetUniformLocation(mat
->prog
, "diffTex");
405 mat
->uSpecTex
= glGetUniformLocation(mat
->prog
, "specTex");
407 uAmbientLight
= glGetUniformLocation(mat
->prog
, "ambientLight");
408 uDiffuseLight
= glGetUniformLocation(mat
->prog
, "diffuseLight");
409 uSpecularLight
= glGetUniformLocation(mat
->prog
, "specularLight");
411 glUniform4fv(mat
->uAmbient
, 1, mat
->ambient
);
412 glUniform4fv(mat
->uDiffuse
, 1, mat
->diffuse
);
413 glUniform4fv(mat
->uSpecular
, 1, mat
->specular
);
414 glUniform1f(mat
->uShininess
, mat
->shininess
);
415 glUniform1i(mat
->uDiffTex
, 0);
416 glUniform1i(mat
->uSpecTex
, 1);
418 glUniform4fv(uAmbientLight
, 1, ambientLight
);
419 glUniform4fv(uDiffuseLight
, 1, diffuseLight
);
420 glUniform4fv(uSpecularLight
, 1, specularLight
);
423 glActiveTexture(GL_TEXTURE1
);
425 glBindTexture(GL_TEXTURE_CUBE_MAP
, mat
->texture_ks
);
427 glBindTexture(GL_TEXTURE_CUBE_MAP
, 0);
429 glActiveTexture(GL_TEXTURE0
);
431 glBindTexture(GL_TEXTURE_2D
, mat
->texture_kd
);
433 glBindTexture(GL_TEXTURE_2D
, 0);
435 if (mat
->diffuse
[3] < 1.0) {
437 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
443 glUseProgram(mat
->prog
);
448 glmSpecularTexture(GLMmodel
*model
, uint cubeTex
)
452 for (i
= 0; i
< model
->nummaterials
; i
++) {
453 model
->materials
[i
].texture_ks
= cubeTex
;