Bump mapping (hardcoded to palette 100 for now, will do the defs glue later to make it more convenient to package the source for public releases).

TODO: use the inverse TBN on a world-space light vector instead of transforming every fragment interpolated normal into eye-space with the TBN * the view matrix.

git-svn-id: https://svn.eduke32.com/eduke32@1244 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
plagman 2009-03-13 15:18:46 +00:00
parent 62d3116325
commit f982323443
2 changed files with 132 additions and 32 deletions

View file

@ -45,6 +45,7 @@ typedef enum {
PR_BIT_HEADER, // must be first PR_BIT_HEADER, // must be first
PR_BIT_ANIM_INTERPOLATION, PR_BIT_ANIM_INTERPOLATION,
PR_BIT_LIGHTING_PASS, PR_BIT_LIGHTING_PASS,
PR_BIT_NORMAL_MAP,
PR_BIT_DIFFUSE_MAP, PR_BIT_DIFFUSE_MAP,
PR_BIT_DIFFUSE_DETAIL_MAP, PR_BIT_DIFFUSE_DETAIL_MAP,
PR_BIT_DIFFUSE_MODULATION, PR_BIT_DIFFUSE_MODULATION,
@ -59,6 +60,8 @@ typedef struct s_prmaterial {
GLfloat frameprogress; GLfloat frameprogress;
GLfloat* nextframedata; GLfloat* nextframedata;
GLsizei nextframedatastride; GLsizei nextframedatastride;
// PR_BIT_NORMAL_MAP
GLuint normalmap;
// PR_BIT_DIFFUSE_MAP // PR_BIT_DIFFUSE_MAP
GLuint diffusemap; GLuint diffusemap;
GLfloat diffusescale[2]; GLfloat diffusescale[2];
@ -77,6 +80,11 @@ typedef struct s_prrograminfo {
GLint attrib_nextFrameData; GLint attrib_nextFrameData;
GLint attrib_nextFrameNormal; GLint attrib_nextFrameNormal;
GLint uniform_frameProgress; GLint uniform_frameProgress;
// PR_BIT_NORMAL_MAP
GLint uniform_normalMap;
GLint attrib_T;
GLint attrib_B;
GLint attrib_N;
// PR_BIT_DIFFUSE_MAP // PR_BIT_DIFFUSE_MAP
GLint uniform_diffuseMap; GLint uniform_diffuseMap;
GLint uniform_diffuseScale; GLint uniform_diffuseScale;

View file

@ -176,19 +176,44 @@ _prprogrambit prprogrambits[PR_BIT_COUNT] = {
" result = vec4(0.0, 0.0, 0.0, 1.0);\n" " result = vec4(0.0, 0.0, 0.0, 1.0);\n"
"\n", "\n",
}, },
{
1 << PR_BIT_NORMAL_MAP,
// vert_def
"attribute vec3 T;\n"
"attribute vec3 B;\n"
"attribute vec3 N;\n"
"varying mat3 matTBN;\n"
"\n",
// vert_prog
" //TBN = mat3(gl_NormalMatrix * T, gl_NormalMatrix * B, gl_NormalMatrix * N);\n"
" matTBN = gl_NormalMatrix * mat3(T, B, N);\n"
"\n"
" gl_TexCoord[texCoord++] = gl_MultiTexCoord0;\n"
" isNormalMapped = 1;\n"
"\n",
// frag_def
"uniform sampler2D normalMap;\n"
"varying mat3 matTBN;\n"
"\n",
// frag_prog
" normalTexel = texture2D(normalMap, gl_TexCoord[texCoord++].st);\n"
" isNormalMapped = 1;\n"
" TBN = matTBN;\n"
"\n",
},
{ {
1 << PR_BIT_DIFFUSE_MAP, 1 << PR_BIT_DIFFUSE_MAP,
// vert_def // vert_def
"uniform vec2 diffuseScale;\n" "uniform vec2 diffuseScale;\n"
"\n", "\n",
// vert_prog // vert_prog
" gl_TexCoord[0] = vec4(diffuseScale, 1.0, 1.0) * gl_MultiTexCoord0;\n" " gl_TexCoord[texCoord++] = vec4(diffuseScale, 1.0, 1.0) * gl_MultiTexCoord0;\n"
"\n", "\n",
// frag_def // frag_def
"uniform sampler2D diffuseMap;\n" "uniform sampler2D diffuseMap;\n"
"\n", "\n",
// frag_prog // frag_prog
" diffuseTexel = texture2D(diffuseMap, gl_TexCoord[0].st);\n" " diffuseTexel = texture2D(diffuseMap, gl_TexCoord[texCoord++].st);\n"
" if (isLightingPass == 0)\n" " if (isLightingPass == 0)\n"
" result *= diffuseTexel;\n" " result *= diffuseTexel;\n"
"\n", "\n",
@ -199,13 +224,13 @@ _prprogrambit prprogrambits[PR_BIT_COUNT] = {
"uniform vec2 detailScale;\n" "uniform vec2 detailScale;\n"
"\n", "\n",
// vert_prog // vert_prog
" gl_TexCoord[1] = vec4(detailScale, 1.0, 1.0) * gl_MultiTexCoord0;\n" " gl_TexCoord[texCoord++] = vec4(detailScale, 1.0, 1.0) * gl_MultiTexCoord0;\n"
"\n", "\n",
// frag_def // frag_def
"uniform sampler2D detailMap;\n" "uniform sampler2D detailMap;\n"
"\n", "\n",
// frag_prog // frag_prog
" result *= texture2D(detailMap, gl_TexCoord[1].st);\n" " result *= texture2D(detailMap, gl_TexCoord[texCoord++].st);\n"
" result.rgb *= 2.0;\n" " result.rgb *= 2.0;\n"
"\n", "\n",
}, },
@ -228,7 +253,7 @@ _prprogrambit prprogrambits[PR_BIT_COUNT] = {
// vert_def // vert_def
"", "",
// vert_prog // vert_prog
" gl_TexCoord[2] = gl_MultiTexCoord0;\n" " gl_TexCoord[texCoord++] = gl_MultiTexCoord0;\n"
"\n", "\n",
// frag_def // frag_def
"uniform sampler2D glowMap;\n" "uniform sampler2D glowMap;\n"
@ -236,7 +261,7 @@ _prprogrambit prprogrambits[PR_BIT_COUNT] = {
// frag_prog // frag_prog
" vec4 glowTexel;\n" " vec4 glowTexel;\n"
"\n" "\n"
" glowTexel = texture2D(glowMap, gl_TexCoord[2].st);\n" " glowTexel = texture2D(glowMap, gl_TexCoord[texCoord++].st);\n"
" result = vec4((result.rgb * (1.0 - glowTexel.a)) + (glowTexel.rgb * glowTexel.a), result.a);\n" " result = vec4((result.rgb * (1.0 - glowTexel.a)) + (glowTexel.rgb * glowTexel.a), result.a);\n"
"\n", "\n",
}, },
@ -246,19 +271,26 @@ _prprogrambit prprogrambits[PR_BIT_COUNT] = {
"varying vec3 vertexNormal;\n" "varying vec3 vertexNormal;\n"
"varying vec3 eyeVector;\n" "varying vec3 eyeVector;\n"
"varying vec3 lightVector;\n" "varying vec3 lightVector;\n"
"varying vec3 tangentSpaceLightVector;\n"
"\n", "\n",
// vert_prog // vert_prog
" vec3 vertexPos;\n" " vec3 vertexPos;\n"
"\n" "\n"
" vertexNormal = normalize(gl_NormalMatrix * curNormal);\n"
" vertexPos = vec3(gl_ModelViewMatrix * curVertex);\n" " vertexPos = vec3(gl_ModelViewMatrix * curVertex);\n"
" eyeVector = -vertexPos;\n" " eyeVector = -vertexPos;\n"
" lightVector = gl_LightSource[0].ambient.rgb - vertexPos;\n" " lightVector = gl_LightSource[0].ambient.rgb - vertexPos;\n"
"\n"
" if (isNormalMapped == 1) {\n"
" tangentSpaceLightVector = vec3(32376.0, -94.0, -32496.0) - vec3(curVertex);\n"
" tangentSpaceLightVector = TBN * tangentSpaceLightVector;\n"
" } else\n"
" vertexNormal = normalize(gl_NormalMatrix * curNormal);\n"
"\n", "\n",
// frag_def // frag_def
"varying vec3 vertexNormal;\n" "varying vec3 vertexNormal;\n"
"varying vec3 eyeVector;\n" "varying vec3 eyeVector;\n"
"varying vec3 lightVector;\n" "varying vec3 lightVector;\n"
"varying vec3 tangentSpaceLightVector;\n"
"\n", "\n",
// frag_prog // frag_prog
" vec2 lightRange;\n" " vec2 lightRange;\n"
@ -284,7 +316,11 @@ _prprogrambit prprogrambits[PR_BIT_COUNT] = {
" (lightRange.y - lightRange.x);\n" " (lightRange.y - lightRange.x);\n"
"\n" "\n"
" if (lightAttenuation > 0.0) {\n" " if (lightAttenuation > 0.0) {\n"
" N = normalize(vertexNormal);\n" " if (isNormalMapped == 1) {\n"
" N = 2.0 * (normalTexel.rgb - 0.5);\n"
" N = normalize(TBN * N);\n"
" } else\n"
" N = normalize(vertexNormal);\n"
" NdotL = dot(N, L);\n" " NdotL = dot(N, L);\n"
"\n" "\n"
" if (NdotL > 0.0) {\n" " if (NdotL > 0.0) {\n"
@ -306,8 +342,11 @@ _prprogrambit prprogrambits[PR_BIT_COUNT] = {
// vert_def // vert_def
"void main(void)\n" "void main(void)\n"
"{\n" "{\n"
" int texCoord = 0;\n"
" vec4 curVertex = gl_Vertex;\n" " vec4 curVertex = gl_Vertex;\n"
" vec3 curNormal = gl_Normal;\n" " vec3 curNormal = gl_Normal;\n"
" int isNormalMapped = 0;\n"
" mat3 TBN;\n"
"\n", "\n",
// vert_prog // vert_prog
" gl_Position = gl_ModelViewProjectionMatrix * curVertex;\n" " gl_Position = gl_ModelViewProjectionMatrix * curVertex;\n"
@ -315,9 +354,13 @@ _prprogrambit prprogrambits[PR_BIT_COUNT] = {
// frag_def // frag_def
"void main(void)\n" "void main(void)\n"
"{\n" "{\n"
" int texCoord = 0;\n"
" vec4 result = vec4(1.0, 1.0, 1.0, 1.0);\n" " vec4 result = vec4(1.0, 1.0, 1.0, 1.0);\n"
" vec4 diffuseTexel = vec4(1.0, 1.0, 1.0, 1.0);\n" " vec4 diffuseTexel = vec4(1.0, 1.0, 1.0, 1.0);\n"
" vec4 normalTexel;\n"
" int isLightingPass = 0;\n" " int isLightingPass = 0;\n"
" int isNormalMapped = 0;\n"
" mat3 TBN;\n"
"\n", "\n",
// frag_prog // frag_prog
" gl_FragColor = result;\n" " gl_FragColor = result;\n"
@ -826,6 +869,9 @@ void polymer_resetlights(void)
void polymer_addlight(_prlight light) void polymer_addlight(_prlight light)
{ {
if (light.sector == -1)
return;
if (lightcount < PR_MAXLIGHTS) if (lightcount < PR_MAXLIGHTS)
{ {
prlights[lightcount] = light; prlights[lightcount] = light;
@ -1240,6 +1286,13 @@ static void polymer_drawplane(int16_t sectnum, int16_t wallnum, _prplane
{ {
materialbits = polymer_bindmaterial(plane->material, plane->lights, plane->lightcount); materialbits = polymer_bindmaterial(plane->material, plane->lights, plane->lightcount);
if (materialbits & prprogrambits[PR_BIT_NORMAL_MAP].bit)
{
bglVertexAttrib3fvARB(prprograms[materialbits].attrib_T, plane->t);
bglVertexAttrib3fvARB(prprograms[materialbits].attrib_B, plane->b);
bglVertexAttrib3fvARB(prprograms[materialbits].attrib_N, plane->plane);
}
if (plane->vbo && (pr_vbos > 0)) if (plane->vbo && (pr_vbos > 0))
{ {
OMGDRAWSHITVBO; OMGDRAWSHITVBO;
@ -2114,9 +2167,12 @@ static void polymer_updatewall(int16_t wallnum)
w->cap[7] += 1048576; // this number is the result of 1048574 + 2 w->cap[7] += 1048576; // this number is the result of 1048574 + 2
w->cap[10] += 1048576; // this one is arbitrary w->cap[10] += 1048576; // this one is arbitrary
polymer_buffertoplane(w->bigportal, NULL, 4, w->wall.plane, w->wall.t, w->wall.b, w->wall.n); if (w->underover & 1)
memcpy(w->over.plane, w->wall.plane, sizeof(w->wall.plane)); polymer_buffertoplane(w->wall.buffer, NULL, 4, w->wall.plane, w->wall.t, w->wall.b, w->wall.n);
memcpy(w->mask.plane, w->wall.plane, sizeof(w->wall.plane)); if (w->underover & 2)
polymer_buffertoplane(w->over.buffer, NULL, 4, w->over.plane, w->over.t, w->over.b, w->over.n);
if (!((wal->nextsector == -1) || (wal->cstat & 32)))
polymer_buffertoplane(w->mask.buffer, NULL, 4, w->mask.plane, w->mask.t, w->mask.b, w->mask.n);
if ((pr_vbos > 0)) if ((pr_vbos > 0))
{ {
@ -2229,27 +2285,27 @@ static void polymer_buffertoplane(GLfloat* buffer, GLushort* indices, in
b[1] = (vec1[3] * vec2[1] - vec2[3] * vec1[1]) * r; b[1] = (vec1[3] * vec2[1] - vec2[3] * vec1[1]) * r;
b[2] = (vec1[3] * vec2[2] - vec2[3] * vec1[2]) * r; b[2] = (vec1[3] * vec2[2] - vec2[3] * vec1[2]) * r;
// invert T, B and N // // invert T, B and N
r = 1.0f / ((t[0] * b[1] * plane[2] - t[2] * b[1] * plane[0]) + // r = 1.0f / ((t[0] * b[1] * plane[2] - t[2] * b[1] * plane[0]) +
(b[0] * plane[1] * t[2] - b[2] * plane[1] * t[0]) + // (b[0] * plane[1] * t[2] - b[2] * plane[1] * t[0]) +
(plane[0] * t[1] * b[2] - plane[2] * t[1] * b[0])); // (plane[0] * t[1] * b[2] - plane[2] * t[1] * b[0]));
//
polymer_crossproduct(b, plane, BxN); // polymer_crossproduct(b, plane, BxN);
polymer_crossproduct(plane, t, NxT); // polymer_crossproduct(plane, t, NxT);
polymer_crossproduct(t, b, TxB); // polymer_crossproduct(t, b, TxB);
//
// GLSL matrix constructors are in column-major order // // GLSL matrix constructors are in column-major order
t[0] = BxN[0] * r; // t[0] = BxN[0] * r;
t[1] = -NxT[0] * r; // t[1] = -NxT[0] * r;
t[2] = TxB[0] * r; // t[2] = TxB[0] * r;
//
b[0] = -BxN[1] * r; // b[0] = -BxN[1] * r;
b[1] = NxT[1] * r; // b[1] = NxT[1] * r;
b[2] = -TxB[1] * r; // b[2] = -TxB[1] * r;
//
n[0] = BxN[2] * r; // n[0] = BxN[2] * r;
n[1] = -NxT[2] * r; // n[1] = -NxT[2] * r;
n[2] = TxB[2] * r; // n[2] = TxB[2] * r;
// normalize T, B and N // normalize T, B and N
norm = t[0] * t[0] + t[1] * t[1] + t[2] * t[2]; norm = t[0] * t[0] + t[1] * t[1] + t[2] * t[2];
@ -2873,6 +2929,8 @@ static void polymer_getscratchmaterial(_prmaterial* material)
material->frameprogress = 0.0f; material->frameprogress = 0.0f;
material->nextframedata = NULL; material->nextframedata = NULL;
material->nextframedatastride = 0; material->nextframedatastride = 0;
// PR_BIT_NORMAL_MAP
material->normalmap = 0;
// PR_BIT_DIFFUSE_MAP // PR_BIT_DIFFUSE_MAP
material->diffusemap = 0; material->diffusemap = 0;
material->diffusescale[0] = material->diffusescale[1] = 1.0f; material->diffusescale[0] = material->diffusescale[1] = 1.0f;
@ -2896,6 +2954,16 @@ static void polymer_getbuildmaterial(_prmaterial* material, int16_t tile
polymer_getscratchmaterial(material); polymer_getscratchmaterial(material);
// PR_BIT_NORMAL_MAP
if (hicfindsubst(tilenum, 100, 0))
{
glowpth = NULL;
glowpth = gltexcache(tilenum, 100, 0);
if (glowpth && glowpth->hicr && (glowpth->hicr->palnum == 100))
material->normalmap = glowpth->glpic;
}
// PR_BIT_DIFFUSE_MAP // PR_BIT_DIFFUSE_MAP
if (!waloff[tilenum]) if (!waloff[tilenum])
loadtile(tilenum); loadtile(tilenum);
@ -2979,6 +3047,10 @@ static int32_t polymer_bindmaterial(_prmaterial material, char* lights, int
if (curlight && lightcount) if (curlight && lightcount)
programbits |= prprogrambits[PR_BIT_LIGHTING_PASS].bit; programbits |= prprogrambits[PR_BIT_LIGHTING_PASS].bit;
// PR_BIT_NORMAL_MAP
if (material.normalmap)
programbits |= prprogrambits[PR_BIT_NORMAL_MAP].bit;
// PR_BIT_DIFFUSE_MAP // PR_BIT_DIFFUSE_MAP
if (material.diffusemap) if (material.diffusemap)
programbits |= prprogrambits[PR_BIT_DIFFUSE_MAP].bit; programbits |= prprogrambits[PR_BIT_DIFFUSE_MAP].bit;
@ -3032,6 +3104,17 @@ static int32_t polymer_bindmaterial(_prmaterial material, char* lights, int
bglBlendFunc(GL_ONE, GL_ONE); bglBlendFunc(GL_ONE, GL_ONE);
} }
// PR_BIT_NORMAL_MAP
if (programbits & prprogrambits[PR_BIT_NORMAL_MAP].bit)
{
bglActiveTextureARB(texunit + GL_TEXTURE0_ARB);
bglBindTexture(GL_TEXTURE_2D, material.normalmap);
bglUniform1iARB(prprograms[programbits].uniform_normalMap, texunit);
texunit++;
}
// PR_BIT_DIFFUSE_MAP // PR_BIT_DIFFUSE_MAP
if (programbits & prprogrambits[PR_BIT_DIFFUSE_MAP].bit) if (programbits & prprogrambits[PR_BIT_DIFFUSE_MAP].bit)
{ {
@ -3210,6 +3293,15 @@ static void polymer_compileprogram(int32_t programbits)
prprograms[programbits].uniform_frameProgress = bglGetUniformLocationARB(program, "frameProgress"); prprograms[programbits].uniform_frameProgress = bglGetUniformLocationARB(program, "frameProgress");
} }
// PR_BIT_NORMAL_MAP
if (programbits & prprogrambits[PR_BIT_NORMAL_MAP].bit)
{
prprograms[programbits].uniform_normalMap = bglGetUniformLocationARB(program, "normalMap");
prprograms[programbits].attrib_T = bglGetAttribLocationARB(program, "T");
prprograms[programbits].attrib_B = bglGetAttribLocationARB(program, "B");
prprograms[programbits].attrib_N = bglGetAttribLocationARB(program, "N");
}
// PR_BIT_DIFFUSE_MAP // PR_BIT_DIFFUSE_MAP
if (programbits & prprogrambits[PR_BIT_DIFFUSE_MAP].bit) if (programbits & prprogrambits[PR_BIT_DIFFUSE_MAP].bit)
{ {