132001f49Smrg/* */
232001f49Smrg
332001f49Smrg#define GL_GLEXT_PROTOTYPES
432001f49Smrg
532001f49Smrg#include <assert.h>
632001f49Smrg#include <stdio.h>
732001f49Smrg#include <stdlib.h>
832001f49Smrg#include <string.h>
932001f49Smrg#include <GL/glew.h>
1032001f49Smrg#include "glm.h"
1132001f49Smrg#include "readtex.h"
1232001f49Smrg#include "shaderutil.h"
1332001f49Smrg
1432001f49Smrg
1532001f49Smrg/* defines */
1632001f49Smrg#define T(x) model->triangles[(x)]
1732001f49Smrg
1832001f49Smrg
1932001f49Smrg/* glmDraw: Renders the model to the current OpenGL context using the
2032001f49Smrg * mode specified.
2132001f49Smrg *
2232001f49Smrg * model    - initialized GLMmodel structure
2332001f49Smrg * mode     - a bitwise OR of values describing what is to be rendered.
2432001f49Smrg *            GLM_NONE     -  render with only vertices
2532001f49Smrg *            GLM_FLAT     -  render with facet normals
2632001f49Smrg *            GLM_SMOOTH   -  render with vertex normals
2732001f49Smrg *            GLM_TEXTURE  -  render with texture coords
2832001f49Smrg *            GLM_COLOR    -  render with colors (color material)
2932001f49Smrg *            GLM_MATERIAL -  render with materials
3032001f49Smrg *            GLM_COLOR and GLM_MATERIAL should not both be specified.
3132001f49Smrg *            GLM_FLAT and GLM_SMOOTH should not both be specified.
3232001f49Smrg */
3332001f49SmrgGLvoid
3432001f49SmrgglmDraw(GLMmodel* model, GLuint mode)
3532001f49Smrg{
3632001f49Smrg  GLuint i;
3732001f49Smrg  GLMgroup* group;
3832001f49Smrg
3932001f49Smrg  assert(model);
4032001f49Smrg  assert(model->vertices);
4132001f49Smrg
4232001f49Smrg  /* do a bit of warning */
4332001f49Smrg  if (mode & GLM_FLAT && !model->facetnorms) {
4432001f49Smrg    printf("glmDraw() warning: flat render mode requested "
4532001f49Smrg	   "with no facet normals defined.\n");
4632001f49Smrg    mode &= ~GLM_FLAT;
4732001f49Smrg  }
4832001f49Smrg  if (mode & GLM_SMOOTH && !model->normals) {
4932001f49Smrg    printf("glmDraw() warning: smooth render mode requested "
5032001f49Smrg	   "with no normals defined.\n");
5132001f49Smrg    mode &= ~GLM_SMOOTH;
5232001f49Smrg  }
5332001f49Smrg  if (mode & GLM_TEXTURE && !model->texcoords) {
5432001f49Smrg    printf("glmDraw() warning: texture render mode requested "
5532001f49Smrg	   "with no texture coordinates defined.\n");
5632001f49Smrg    mode &= ~GLM_TEXTURE;
5732001f49Smrg  }
5832001f49Smrg  if (mode & GLM_FLAT && mode & GLM_SMOOTH) {
5932001f49Smrg    printf("glmDraw() warning: flat render mode requested "
6032001f49Smrg	   "and smooth render mode requested (using smooth).\n");
6132001f49Smrg    mode &= ~GLM_FLAT;
6232001f49Smrg  }
6332001f49Smrg  if (mode & GLM_COLOR && !model->materials) {
6432001f49Smrg    printf("glmDraw() warning: color render mode requested "
6532001f49Smrg	   "with no materials defined.\n");
6632001f49Smrg    mode &= ~GLM_COLOR;
6732001f49Smrg  }
6832001f49Smrg  if (mode & GLM_MATERIAL && !model->materials) {
6932001f49Smrg    printf("glmDraw() warning: material render mode requested "
7032001f49Smrg	   "with no materials defined.\n");
7132001f49Smrg    mode &= ~GLM_MATERIAL;
7232001f49Smrg  }
7332001f49Smrg  if (mode & GLM_COLOR && mode & GLM_MATERIAL) {
7432001f49Smrg    printf("glmDraw() warning: color and material render mode requested "
7532001f49Smrg	   "using only material mode\n");
7632001f49Smrg    mode &= ~GLM_COLOR;
7732001f49Smrg  }
7832001f49Smrg  if (mode & GLM_COLOR)
7932001f49Smrg    glEnable(GL_COLOR_MATERIAL);
8032001f49Smrg  if (mode & GLM_MATERIAL)
8132001f49Smrg    glDisable(GL_COLOR_MATERIAL);
8232001f49Smrg
8332001f49Smrg  glPushMatrix();
8432001f49Smrg  glTranslatef(model->position[0], model->position[1], model->position[2]);
8532001f49Smrg
8632001f49Smrg  glBegin(GL_TRIANGLES);
8732001f49Smrg  group = model->groups;
8832001f49Smrg  while (group) {
8932001f49Smrg    if (mode & GLM_MATERIAL) {
9032001f49Smrg      glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT,
9132001f49Smrg		   model->materials[group->material].ambient);
9232001f49Smrg      glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE,
9332001f49Smrg		   model->materials[group->material].diffuse);
9432001f49Smrg      glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR,
9532001f49Smrg		   model->materials[group->material].specular);
9632001f49Smrg       glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS,
9732001f49Smrg  		  model->materials[group->material].shininess);
9832001f49Smrg    }
9932001f49Smrg
10032001f49Smrg    if (mode & GLM_COLOR) {
10132001f49Smrg      glColor3fv(model->materials[group->material].diffuse);
10232001f49Smrg    }
10332001f49Smrg
10432001f49Smrg    for (i = 0; i < group->numtriangles; i++) {
10532001f49Smrg      if (mode & GLM_FLAT)
10632001f49Smrg	glNormal3fv(&model->facetnorms[3 * T(group->triangles[i]).findex]);
10732001f49Smrg
10832001f49Smrg      if (mode & GLM_SMOOTH)
10932001f49Smrg	glNormal3fv(&model->normals[3 * T(group->triangles[i]).nindices[0]]);
11032001f49Smrg      if (mode & GLM_TEXTURE)
11132001f49Smrg	glTexCoord2fv(&model->texcoords[2*T(group->triangles[i]).tindices[0]]);
11232001f49Smrg      glVertex3fv(&model->vertices[3 * T(group->triangles[i]).vindices[0]]);
11332001f49Smrg#if 0
11432001f49Smrg      printf("%f %f %f\n",
11532001f49Smrg	     model->vertices[3 * T(group->triangles[i]).vindices[0] + X],
11632001f49Smrg	     model->vertices[3 * T(group->triangles[i]).vindices[0] + Y],
11732001f49Smrg	     model->vertices[3 * T(group->triangles[i]).vindices[0] + Z]);
11832001f49Smrg#endif
11932001f49Smrg
12032001f49Smrg      if (mode & GLM_SMOOTH)
12132001f49Smrg	glNormal3fv(&model->normals[3 * T(group->triangles[i]).nindices[1]]);
12232001f49Smrg      if (mode & GLM_TEXTURE)
12332001f49Smrg	glTexCoord2fv(&model->texcoords[2*T(group->triangles[i]).tindices[1]]);
12432001f49Smrg      glVertex3fv(&model->vertices[3 * T(group->triangles[i]).vindices[1]]);
12532001f49Smrg#if 0
12632001f49Smrg      printf("%f %f %f\n",
12732001f49Smrg	     model->vertices[3 * T(group->triangles[i]).vindices[1] + X],
12832001f49Smrg	     model->vertices[3 * T(group->triangles[i]).vindices[1] + Y],
12932001f49Smrg	     model->vertices[3 * T(group->triangles[i]).vindices[1] + Z]);
13032001f49Smrg#endif
13132001f49Smrg
13232001f49Smrg      if (mode & GLM_SMOOTH)
13332001f49Smrg	glNormal3fv(&model->normals[3 * T(group->triangles[i]).nindices[2]]);
13432001f49Smrg      if (mode & GLM_TEXTURE)
13532001f49Smrg	glTexCoord2fv(&model->texcoords[2*T(group->triangles[i]).tindices[2]]);
13632001f49Smrg      glVertex3fv(&model->vertices[3 * T(group->triangles[i]).vindices[2]]);
13732001f49Smrg#if 0
13832001f49Smrg      printf("%f %f %f\n",
13932001f49Smrg	     model->vertices[3 * T(group->triangles[i]).vindices[2] + X],
14032001f49Smrg	     model->vertices[3 * T(group->triangles[i]).vindices[2] + Y],
14132001f49Smrg	     model->vertices[3 * T(group->triangles[i]).vindices[2] + Z]);
14232001f49Smrg#endif
14332001f49Smrg
14432001f49Smrg    }
14532001f49Smrg
14632001f49Smrg    group = group->next;
14732001f49Smrg  }
14832001f49Smrg  glEnd();
14932001f49Smrg
15032001f49Smrg  glPopMatrix();
15132001f49Smrg}
15232001f49Smrg
15332001f49Smrg
15432001f49Smrgvoid
15532001f49SmrgglmMakeVBOs(GLMmodel *model)
15632001f49Smrg{
15732001f49Smrg   uint bytes, vertexFloats, i;
15832001f49Smrg   float *buffer;
15932001f49Smrg   GLMgroup* group;
16032001f49Smrg   unsigned totalIndexes;
16132001f49Smrg   GLubyte *ibuffer, *ib;
16232001f49Smrg
16332001f49Smrg   /*
16432001f49Smrg    * Vertex data
16532001f49Smrg    */
16632001f49Smrg   vertexFloats = 3;
16732001f49Smrg   model->posOffset = 0;
16832001f49Smrg
16932001f49Smrg   if (model->numnormals > 0) {
17032001f49Smrg      assert(model->numnormals == model->numvertices);
17132001f49Smrg      model->normOffset = vertexFloats * sizeof(GLfloat);
17232001f49Smrg      vertexFloats += 3;
17332001f49Smrg   }
17432001f49Smrg
17532001f49Smrg   if (model->numtexcoords > 0) {
17632001f49Smrg      assert(model->numtexcoords == model->numvertices);
17732001f49Smrg      model->texOffset = vertexFloats * sizeof(GLfloat);
17832001f49Smrg      vertexFloats += 2;
17932001f49Smrg   }
18032001f49Smrg
18132001f49Smrg   model->vertexSize = vertexFloats;
18232001f49Smrg
18332001f49Smrg   bytes = (model->numvertices + 1) * vertexFloats * sizeof(float);
18432001f49Smrg
18532001f49Smrg   buffer = (float *) malloc(bytes);
18632001f49Smrg   for (i = 0; i < model->numvertices; i++) {
18732001f49Smrg      /* copy vertex pos */
18832001f49Smrg      uint j = 0;
18932001f49Smrg      buffer[i * vertexFloats + j++] = model->vertices[i * 3 + 0];
19032001f49Smrg      buffer[i * vertexFloats + j++] = model->vertices[i * 3 + 1];
19132001f49Smrg      buffer[i * vertexFloats + j++] = model->vertices[i * 3 + 2];
19232001f49Smrg      if (model->numnormals > 0) {
19332001f49Smrg         buffer[i * vertexFloats + j++] = model->normals[i * 3 + 0];
19432001f49Smrg         buffer[i * vertexFloats + j++] = model->normals[i * 3 + 1];
19532001f49Smrg         buffer[i * vertexFloats + j++] = model->normals[i * 3 + 2];
19632001f49Smrg      }
19732001f49Smrg      if (model->numtexcoords > 0) {
19832001f49Smrg         buffer[i * vertexFloats + j++] = model->texcoords[i * 2 + 0];
19932001f49Smrg         buffer[i * vertexFloats + j++] = model->texcoords[i * 2 + 1];
20032001f49Smrg      }
20132001f49Smrg   }
20232001f49Smrg
20332001f49Smrg   glGenBuffersARB(1, &model->vbo);
20432001f49Smrg   glBindBufferARB(GL_ARRAY_BUFFER_ARB, model->vbo);
20532001f49Smrg   glBufferDataARB(GL_ARRAY_BUFFER_ARB, bytes, buffer, GL_STATIC_DRAW_ARB);
20632001f49Smrg   glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
20732001f49Smrg
20832001f49Smrg   free(buffer);
20932001f49Smrg
21032001f49Smrg   /*
21132001f49Smrg    * Index data
21232001f49Smrg    */
21332001f49Smrg   totalIndexes = 0;
21432001f49Smrg   for (group = model->groups; group; group = group->next) {
21532001f49Smrg      if (group->numtriangles > 0) {
21632001f49Smrg         totalIndexes += 3 * group->numtriangles;
21732001f49Smrg      }
21832001f49Smrg   }
21932001f49Smrg
22032001f49Smrg   glGenBuffersARB(1, &model->index_vbo);
22132001f49Smrg   glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, model->index_vbo);
22232001f49Smrg   glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, totalIndexes * sizeof(GLuint),
22332001f49Smrg                   NULL, GL_STATIC_DRAW_ARB);
22432001f49Smrg   ibuffer = (GLubyte *) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB,
22532001f49Smrg                                        GL_WRITE_ONLY);
22632001f49Smrg   ib = ibuffer;
22732001f49Smrg
22832001f49Smrg   for (group = model->groups; group; group = group->next) {
22932001f49Smrg      if (group->numtriangles > 0) {
23032001f49Smrg         int bytes = 3 * group->numtriangles * sizeof(uint);
23132001f49Smrg         memcpy(ib, group->triIndexes, bytes);
23232001f49Smrg         totalIndexes += 3 * group->numtriangles;
23332001f49Smrg         group->indexVboOffset = ib - ibuffer;
23432001f49Smrg         ib += bytes;
23532001f49Smrg      }
23632001f49Smrg   }
23732001f49Smrg
23832001f49Smrg   glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB);
23932001f49Smrg
24032001f49Smrg   glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
24132001f49Smrg}
24232001f49Smrg
24332001f49Smrg
24432001f49Smrgstatic void
24532001f49Smrg_glmLoadTexture(GLMmaterial *mat)
24632001f49Smrg{
24732001f49Smrg  if (mat->map_kd) {
24832001f49Smrg     GLint imgWidth, imgHeight;
24932001f49Smrg     GLenum imgFormat;
25032001f49Smrg     GLubyte *image = NULL;
25132001f49Smrg
25232001f49Smrg     glGenTextures(1, &mat->texture_kd);
25332001f49Smrg
25432001f49Smrg     image = LoadRGBImage( mat->map_kd, &imgWidth, &imgHeight, &imgFormat );
25532001f49Smrg     if (!image) {
25632001f49Smrg        /*fprintf(stderr, "Couldn't open texture %s\n", mat->map_kd);*/
25732001f49Smrg        free(mat->map_kd);
25832001f49Smrg        mat->map_kd = NULL;
25932001f49Smrg        mat->texture_kd = 0;
26032001f49Smrg        return;
26132001f49Smrg     }
26232001f49Smrg     if (0)
26332001f49Smrg        printf("load texture %s %d x %d\n", mat->map_kd, imgWidth, imgHeight);
26432001f49Smrg
26532001f49Smrg     glBindTexture(GL_TEXTURE_2D, mat->texture_kd);
26632001f49Smrg     gluBuild2DMipmaps(GL_TEXTURE_2D, 3, imgWidth, imgHeight,
26732001f49Smrg                       imgFormat, GL_UNSIGNED_BYTE, image);
26832001f49Smrg     free(image);
26932001f49Smrg
27032001f49Smrg     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
27132001f49Smrg     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
27232001f49Smrg     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
27332001f49Smrg     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
27432001f49Smrg  }
27532001f49Smrg}
27632001f49Smrg
27732001f49Smrgvoid
27832001f49SmrgglmLoadTextures(GLMmodel *model)
27932001f49Smrg{
28032001f49Smrg   uint i;
28132001f49Smrg
28232001f49Smrg   for (i = 0; i < model->nummaterials; i++) {
28332001f49Smrg      GLMmaterial *mat = &model->materials[i];
28432001f49Smrg      _glmLoadTexture(mat);
28532001f49Smrg   }
28632001f49Smrg}
28732001f49Smrg
28832001f49Smrg
28932001f49Smrgvoid
29032001f49SmrgglmDrawVBO(GLMmodel *model)
29132001f49Smrg{
29232001f49Smrg   GLMgroup* group;
29332001f49Smrg   uint prevMaterial = ~0;
29432001f49Smrg
29532001f49Smrg   assert(model->vbo);
29632001f49Smrg
29732001f49Smrg   glBindBufferARB(GL_ARRAY_BUFFER_ARB, model->vbo);
29832001f49Smrg
29932001f49Smrg   glVertexPointer(3, GL_FLOAT, model->vertexSize * sizeof(float),
30032001f49Smrg                   (const void *) (size_t) model->posOffset);
30132001f49Smrg   glEnableClientState(GL_VERTEX_ARRAY);
30232001f49Smrg
30332001f49Smrg   if (model->numnormals > 0) {
30432001f49Smrg      glNormalPointer(GL_FLOAT, model->vertexSize * sizeof(float),
30532001f49Smrg                      (const void *) (size_t) model->normOffset);
30632001f49Smrg      glEnableClientState(GL_NORMAL_ARRAY);
30732001f49Smrg   }
30832001f49Smrg
30932001f49Smrg   if (model->numtexcoords > 0) {
31032001f49Smrg      glTexCoordPointer(2, GL_FLOAT, model->vertexSize * sizeof(float),
31132001f49Smrg                        (const void *) (size_t) model->texOffset);
31232001f49Smrg      glEnableClientState(GL_TEXTURE_COORD_ARRAY);
31332001f49Smrg   }
31432001f49Smrg
31532001f49Smrg   glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, model->index_vbo);
31632001f49Smrg
31732001f49Smrg   glPushMatrix();
31832001f49Smrg   glTranslatef(model->position[0], model->position[1], model->position[2]);
31932001f49Smrg   glScalef(model->scale, model->scale, model->scale);
32032001f49Smrg
32132001f49Smrg   for (group = model->groups; group; group = group->next) {
32232001f49Smrg      if (group->numtriangles > 0) {
32332001f49Smrg
32432001f49Smrg         if (group->material != prevMaterial) {
32532001f49Smrg            glmShaderMaterial(&model->materials[group->material]);
32632001f49Smrg            prevMaterial = group->material;
32732001f49Smrg         }
32832001f49Smrg
32932001f49Smrg         glDrawRangeElements(GL_TRIANGLES,
33032001f49Smrg                             group->minIndex, group->maxIndex,
33132001f49Smrg                             3 * group->numtriangles,
33232001f49Smrg                             GL_UNSIGNED_INT,
33332001f49Smrg                             (void *) (GLintptr) group->indexVboOffset);
33432001f49Smrg      }
33532001f49Smrg   }
33632001f49Smrg
33732001f49Smrg   glPopMatrix();
33832001f49Smrg
33932001f49Smrg   glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
34032001f49Smrg   glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
34132001f49Smrg   glDisableClientState(GL_VERTEX_ARRAY);
34232001f49Smrg   glDisableClientState(GL_NORMAL_ARRAY);
34332001f49Smrg   glDisableClientState(GL_TEXTURE_COORD_ARRAY);
34432001f49Smrg}
34532001f49Smrg
34632001f49Smrg
34732001f49Smrg
34832001f49Smrg/* glmList: Generates and returns a display list for the model using
34932001f49Smrg * the mode specified.
35032001f49Smrg *
35132001f49Smrg * model    - initialized GLMmodel structure
35232001f49Smrg * mode     - a bitwise OR of values describing what is to be rendered.
35332001f49Smrg *            GLM_NONE     -  render with only vertices
35432001f49Smrg *            GLM_FLAT     -  render with facet normals
35532001f49Smrg *            GLM_SMOOTH   -  render with vertex normals
35632001f49Smrg *            GLM_TEXTURE  -  render with texture coords
35732001f49Smrg *            GLM_COLOR    -  render with colors (color material)
35832001f49Smrg *            GLM_MATERIAL -  render with materials
35932001f49Smrg *            GLM_COLOR and GLM_MATERIAL should not both be specified.
36032001f49Smrg *            GLM_FLAT and GLM_SMOOTH should not both be specified.
36132001f49Smrg */
36232001f49SmrgGLuint
36332001f49SmrgglmList(GLMmodel* model, GLuint mode)
36432001f49Smrg{
36532001f49Smrg  GLuint list;
36632001f49Smrg
36732001f49Smrg  list = glGenLists(1);
36832001f49Smrg  glNewList(list, GL_COMPILE);
36932001f49Smrg  glmDraw(model, mode);
37032001f49Smrg  glEndList();
37132001f49Smrg
37232001f49Smrg  return list;
37332001f49Smrg}
37432001f49Smrg
37532001f49Smrg
37632001f49Smrg
37732001f49Smrgstatic const char *VertexShader =
37832001f49Smrg   "varying vec3 normal; \n"
37932001f49Smrg   "void main() { \n"
38032001f49Smrg   "   gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; \n"
38132001f49Smrg   "   normal = gl_NormalMatrix * gl_Normal; \n"
38232001f49Smrg   "   gl_TexCoord[0] = gl_MultiTexCoord0; \n"
38332001f49Smrg   "} \n";
38432001f49Smrg
38532001f49Smrg/**
38632001f49Smrg * Two %s substitutions:
38732001f49Smrg *   diffuse texture? true/false
38832001f49Smrg *   specular texture? true/false
38932001f49Smrg */
39032001f49Smrgstatic const char *TexFragmentShader =
39132001f49Smrg   "uniform vec4 ambient, diffuse, specular; \n"
39232001f49Smrg   "uniform vec4 ambientLight, diffuseLight, specularLight; \n"
39332001f49Smrg   "uniform float shininess; \n"
39432001f49Smrg   "uniform sampler2D diffTex; \n"
39532001f49Smrg   "uniform samplerCube specTex; \n"
39632001f49Smrg   "varying vec3 normal; \n"
39732001f49Smrg   "\n"
39832001f49Smrg   "void main() \n"
39932001f49Smrg   "{ \n"
40032001f49Smrg   "   vec4 diffTerm, specTerm; \n"
40132001f49Smrg   "   float dotProd = max(dot(gl_LightSource[0].position.xyz, \n"
40232001f49Smrg   "                           normalize(normal)), 0.0);\n"
40332001f49Smrg   "   float dotProd2 = max(dot(-gl_LightSource[0].position.xyz, \n"
40432001f49Smrg   "                           normalize(normal)), 0.0);\n"
40532001f49Smrg   "   dotProd += dotProd2; \n"
40632001f49Smrg   " \n"
40732001f49Smrg   "   diffTerm = diffuse * diffuseLight * dotProd; \n"
40832001f49Smrg   "   if (%s) \n"
40932001f49Smrg   "      diffTerm *= texture2D(diffTex, gl_TexCoord[0].st); \n"
41032001f49Smrg   " \n"
41132001f49Smrg   "   specTerm = specular * specularLight * pow(dotProd, shininess); \n"
41232001f49Smrg   "   if (%s) \n"
41332001f49Smrg   "      specTerm *= textureCube(specTex, normal); \n"
41432001f49Smrg   " \n"
41532001f49Smrg   "   gl_FragColor = ambient * ambientLight + diffTerm + specTerm; \n"
41632001f49Smrg   "} \n";
41732001f49Smrg
41832001f49Smrg
41932001f49Smrgvoid
42032001f49SmrgglmShaderMaterial(GLMmaterial *mat)
42132001f49Smrg{
42232001f49Smrg   static const float ambientLight[4] = { 0.1, 0.1, 0.1, 0.0 };
42332001f49Smrg   static const float diffuseLight[4] = { 0.75, 0.75, 0.75, 1.0 };
42432001f49Smrg   static const float specularLight[4] = { 1.0, 1.0, 1.0, 0.0 };
42532001f49Smrg
42632001f49Smrg   if (!mat->prog) {
42732001f49Smrg      /* make shader now */
42832001f49Smrg      char newShader[10000];
42932001f49Smrg      GLuint vs, fs;
43032001f49Smrg      const char *diffuseTex = mat->texture_kd ? "true" : "false";
43132001f49Smrg      const char *specularTex = mat->texture_ks ? "true" : "false";
43232001f49Smrg      GLint uAmbientLight, uDiffuseLight, uSpecularLight;
43332001f49Smrg
43432001f49Smrg      /* replace %d with 0 or 1 */
43532001f49Smrg      sprintf(newShader, TexFragmentShader, diffuseTex, specularTex);
43632001f49Smrg      if (0)
43732001f49Smrg         printf("===== new shader =====\n%s\n============\n", newShader);
43832001f49Smrg
43932001f49Smrg      vs = CompileShaderText(GL_VERTEX_SHADER, VertexShader);
44032001f49Smrg      fs = CompileShaderText(GL_FRAGMENT_SHADER, newShader);
44132001f49Smrg      mat->prog = LinkShaders(vs, fs);
44232001f49Smrg      assert(mat->prog);
44332001f49Smrg
44432001f49Smrg      glUseProgram(mat->prog);
44532001f49Smrg
44632001f49Smrg      mat->uAmbient = glGetUniformLocation(mat->prog, "ambient");
44732001f49Smrg      mat->uDiffuse = glGetUniformLocation(mat->prog, "diffuse");
44832001f49Smrg      mat->uSpecular = glGetUniformLocation(mat->prog, "specular");
44932001f49Smrg      mat->uShininess = glGetUniformLocation(mat->prog, "shininess");
45032001f49Smrg      mat->uDiffTex = glGetUniformLocation(mat->prog, "diffTex");
45132001f49Smrg      mat->uSpecTex = glGetUniformLocation(mat->prog, "specTex");
45232001f49Smrg
45332001f49Smrg      uAmbientLight = glGetUniformLocation(mat->prog, "ambientLight");
45432001f49Smrg      uDiffuseLight = glGetUniformLocation(mat->prog, "diffuseLight");
45532001f49Smrg      uSpecularLight = glGetUniformLocation(mat->prog, "specularLight");
45632001f49Smrg
45732001f49Smrg      glUniform4fv(mat->uAmbient, 1, mat->ambient);
45832001f49Smrg      glUniform4fv(mat->uDiffuse, 1, mat->diffuse);
45932001f49Smrg      glUniform4fv(mat->uSpecular, 1, mat->specular);
46032001f49Smrg      glUniform1f(mat->uShininess, mat->shininess);
46132001f49Smrg      glUniform1i(mat->uDiffTex, 0);
46232001f49Smrg      glUniform1i(mat->uSpecTex, 1);
46332001f49Smrg
46432001f49Smrg      glUniform4fv(uAmbientLight, 1, ambientLight);
46532001f49Smrg      glUniform4fv(uDiffuseLight, 1, diffuseLight);
46632001f49Smrg      glUniform4fv(uSpecularLight, 1, specularLight);
46732001f49Smrg   }
46832001f49Smrg
46932001f49Smrg   glActiveTexture(GL_TEXTURE1);
47032001f49Smrg   if (mat->texture_ks)
47132001f49Smrg      glBindTexture(GL_TEXTURE_CUBE_MAP, mat->texture_ks);
47232001f49Smrg   else
47332001f49Smrg      glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
47432001f49Smrg
47532001f49Smrg   glActiveTexture(GL_TEXTURE0);
47632001f49Smrg   if (mat->texture_kd)
47732001f49Smrg      glBindTexture(GL_TEXTURE_2D, mat->texture_kd);
47832001f49Smrg   else
47932001f49Smrg      glBindTexture(GL_TEXTURE_2D, 0);
48032001f49Smrg
48132001f49Smrg   if (mat->diffuse[3] < 1.0) {
48232001f49Smrg      glEnable(GL_BLEND);
48332001f49Smrg      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
48432001f49Smrg   }
48532001f49Smrg   else {
48632001f49Smrg      glDisable(GL_BLEND);
48732001f49Smrg   }
48832001f49Smrg
48932001f49Smrg   glUseProgram(mat->prog);
49032001f49Smrg}
49132001f49Smrg
49232001f49Smrg
49332001f49Smrgvoid
49432001f49SmrgglmSpecularTexture(GLMmodel *model, uint cubeTex)
49532001f49Smrg{
49632001f49Smrg   uint i;
49732001f49Smrg
49832001f49Smrg   for (i = 0; i < model->nummaterials; i++) {
49932001f49Smrg      model->materials[i].texture_ks = cubeTex;
50032001f49Smrg   }
50132001f49Smrg}
502