mirror of
https://github.com/blendogames/thirtyflightsofloving.git
synced 2024-11-15 00:41:21 +00:00
363 lines
10 KiB
C
363 lines
10 KiB
C
/*
|
|
===========================================================================
|
|
Copyright (C) 1997-2001 Id Software, Inc.
|
|
Copyright (C) 2006 Quake2xp Team.
|
|
|
|
This file is part of Quake 2 source code.
|
|
|
|
Quake 2 source code is free software; you can redistribute it
|
|
and/or modify it under the terms of the GNU General Public License as
|
|
published by the Free Software Foundation; either version 2 of the License,
|
|
or (at your option) any later version.
|
|
|
|
Quake 2 source code is distributed in the hope that it will be
|
|
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with Quake 2 source code; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
===========================================================================
|
|
*/
|
|
|
|
#include "r_local.h"
|
|
|
|
//
|
|
// local[0] - distortion strength (comes from cvar, 1.0 is default)
|
|
//
|
|
|
|
static char fragment_program_heathazemask[] =
|
|
"!!ARBfp1.0\n"
|
|
"OPTION ARB_precision_hint_fastest;\n"
|
|
|
|
"TEMP R0, R1, R2;\n"
|
|
|
|
"TEX R0, fragment.texcoord[0], texture[0], 2D;\n"
|
|
|
|
// fetch the water texture
|
|
"ADD R1, R0, fragment.texcoord[2];\n"
|
|
|
|
//"TEX R1, R1, texture[2], 2D;\n" // bump 3th tex
|
|
"TEX R1, fragment.texcoord[2], texture[2], 2D;\n" // dont bump 3th tex
|
|
|
|
// scale offset by the distortion factor
|
|
"MUL R0, R0, fragment.texcoord[3];\n" //error was MUL
|
|
|
|
// apply the alpha mask
|
|
"TEX R2, fragment.texcoord[2], texture[3], 2D;\n"
|
|
"MUL R0, R0, R2;\n"
|
|
|
|
// calculate the screen texcoord in the 0.0 to 1.0 range
|
|
"MUL R2, fragment.position, program.local[0];\n"
|
|
|
|
// offset by the scaled ds/dt and clamp it to 0.0 - 1.0
|
|
"ADD_SAT R2, R0, R2;\n"
|
|
|
|
// scale by the screen non-power-of-two-adjust
|
|
"MUL R2, R2, program.local[1];\n"
|
|
|
|
// fetch the screen texture
|
|
"TEX R2, R2, texture[1], 2D;\n"
|
|
|
|
"MUL R1, R1, fragment.color;\n"
|
|
//"ADD result.color, R2, R1;\n"
|
|
"ADD R2, R2, R1;\n"
|
|
"MUL result.color, R2, program.local[3];\n"
|
|
|
|
"END\n";
|
|
|
|
|
|
/*
|
|
// Original BeefQuake R6 (March 13 2005) GLSL program
|
|
uniform sampler2D texImage;
|
|
uniform sampler2D texDistort;
|
|
|
|
void main() {
|
|
vec4 col;
|
|
vec4 offset;
|
|
float x,y;
|
|
|
|
offset = texture2D(texDistort, vec2(gl_TexCoord[1]));
|
|
x = gl_TexCoord[0].r + offset[2];
|
|
y = gl_TexCoord[0].g + offset[3];
|
|
col = texture2D(texImage, vec2(x,y));
|
|
gl_FragColor = col * gl_Color;
|
|
}
|
|
*/
|
|
|
|
#if 1
|
|
static char fragment_program_warp[] =
|
|
"!!ARBfp1.0\n"
|
|
//"OPTION ARB_precision_hint_fastest;\n"
|
|
"OPTION ARB_precision_hint_nicest;\n"
|
|
|
|
"PARAM rgbscale = program.local[0];\n"
|
|
"TEMP offset, coord, dist, col;\n"
|
|
|
|
"TEX offset, fragment.texcoord[1], texture[1], 2D;\n"
|
|
"MUL offset, offset, 0.5;\n"
|
|
|
|
// fetch the water texture
|
|
"ADD coord.x, fragment.texcoord[0].x, offset.z;\n"
|
|
"ADD coord.y, fragment.texcoord[0].y, offset.w;\n"
|
|
"TEX dist, coord, texture[0], 2D;\n"
|
|
"MUL col, dist, fragment.color;\n"
|
|
|
|
// scale by rgbscale
|
|
"MUL result.color, col, rgbscale;\n"
|
|
|
|
"END\n";
|
|
#else
|
|
static char fragment_program_warp[] =
|
|
"!!ARBfp1.0\n"
|
|
//"OPTION ARB_precision_hint_fastest;\n"
|
|
"OPTION ARB_precision_hint_nicest;\n"
|
|
|
|
"PARAM rgbscale = program.local[0];\n"
|
|
"TEMP offset, coord, dist, col;\n"
|
|
|
|
"TEX offset, fragment.texcoord[0], texture[0], 2D;\n"
|
|
"MUL offset, offset, 0.5;\n"
|
|
|
|
// fetch the water texture
|
|
"ADD coord.x, fragment.texcoord[1].x, offset.z;\n"
|
|
"ADD coord.y, fragment.texcoord[1].y, offset.w;\n"
|
|
"TEX dist, coord, texture[1], 2D;\n"
|
|
"MUL col, dist, fragment.color;\n"
|
|
"MUL result.color, col, rgbscale;\n"
|
|
|
|
"END\n";
|
|
#endif
|
|
|
|
|
|
static char fragment_program_warp_lightmap[] =
|
|
"!!ARBfp1.0\n"
|
|
//"OPTION ARB_precision_hint_fastest;\n"
|
|
"OPTION ARB_precision_hint_nicest;\n"
|
|
|
|
"PARAM rgbscale = program.local[0];\n"
|
|
"TEMP offset, light, coord, dist, unlit, col;\n"
|
|
|
|
"TEX offset, fragment.texcoord[2], texture[2], 2D;\n"
|
|
"MUL offset, offset, 0.5;\n"
|
|
|
|
"TEX light, fragment.texcoord[1], texture[1], 2D;\n"
|
|
"MOV light.w, 1.0;\n"
|
|
|
|
// fetch the water texture
|
|
"ADD coord.x, fragment.texcoord[0].x, offset.z;\n"
|
|
"ADD coord.y, fragment.texcoord[0].y, offset.w;\n"
|
|
"TEX dist, coord, texture[0], 2D;\n"
|
|
"MUL unlit, dist, fragment.color;\n"
|
|
|
|
// blend lightmap
|
|
"MUL col, unlit, light;\n"
|
|
|
|
// scale by rgbscale
|
|
"MUL result.color, col, rgbscale;\n"
|
|
|
|
"END\n";
|
|
|
|
|
|
static char fragment_program_water_distort[] =
|
|
"!!ARBfp1.0\n"
|
|
|
|
// Scroll and scale the distortion texture coordinates.
|
|
// Scroll coordinates are specified externally.
|
|
"PARAM scroll1 = program.local[0];\n"
|
|
"PARAM scroll2 = program.local[1];\n"
|
|
"PARAM texScale1 = { 0.008, 0.008, 1.0, 1.0 };\n"
|
|
"PARAM texScale2 = { 0.007, 0.007, 1.0, 1.0 };\n"
|
|
"TEMP texCoord1;\n"
|
|
"TEMP texCoord2;\n"
|
|
"MUL texCoord1, fragment.texcoord[1], texScale1;\n"
|
|
"MUL texCoord2, fragment.texcoord[1], texScale2;\n"
|
|
"ADD texCoord1, texCoord1, scroll1;\n"
|
|
"ADD texCoord2, texCoord2, scroll2;\n"
|
|
|
|
// Load the distortion textures and add them together.
|
|
"TEMP distortColor;\n"
|
|
"TEMP distortColor2;\n"
|
|
"TXP distortColor, texCoord1, texture[1], 2D;\n"
|
|
"TXP distortColor2, texCoord2, texture[1], 2D;\n"
|
|
"ADD distortColor, distortColor, distortColor2;\n"
|
|
|
|
// Subtract 1.0 and scale by 2.0.
|
|
// Textures will be distorted from -2.0 to 2.0 texels.
|
|
"PARAM scaleFactor = { 2.0, 2.0, 2.0, 2.0 };\n"
|
|
"PARAM one = { 1.0, 1.0, 1.0, 1.0 };\n"
|
|
"SUB distortColor, distortColor, one;\n"
|
|
"MUL distortColor, distortColor, scaleFactor;\n"
|
|
|
|
// Apply distortion to reflection texture coordinates.
|
|
"TEMP distortCoord;\n"
|
|
"TEMP endColor;\n"
|
|
"ADD distortCoord, distortColor, fragment.texcoord[0];\n"
|
|
"TXP endColor, distortCoord, texture, 2D;\n"
|
|
|
|
// Get a vector from the surface to the view origin
|
|
"PARAM vieworg = program.local[2];\n"
|
|
"TEMP eyeVec;\n"
|
|
"TEMP trans;\n"
|
|
"SUB eyeVec, vieworg, fragment.texcoord[1];\n"
|
|
|
|
// Normalize the vector to the eye position
|
|
"TEMP temp;\n"
|
|
"TEMP invLen;\n"
|
|
"DP3 temp, eyeVec, eyeVec;\n"
|
|
"RSQ invLen, temp.x;\n"
|
|
"MUL eyeVec, eyeVec, invLen;\n"
|
|
"ABS eyeVec.z, eyeVec.z;\n" // so it works underwater, too
|
|
|
|
// Load the ripple normal map
|
|
"TEMP normalColor;\n"
|
|
"TEMP normalColor2;\n"
|
|
// Scale texture
|
|
"MUL texCoord1, fragment.texcoord[2], texScale2;\n"
|
|
"MUL texCoord2, fragment.texcoord[2], texScale1;\n"
|
|
// Scroll texture
|
|
"ADD texCoord1, texCoord1, scroll1;\n"
|
|
"ADD texCoord2, texCoord2, scroll2;\n"
|
|
// Get texel color
|
|
"TXP normalColor, texCoord1, texture[2], 2D;\n"
|
|
"TXP normalColor2, texCoord2, texture[2], 2D;\n"
|
|
// Combine normal maps
|
|
"ADD normalColor, normalColor, normalColor2;\n"
|
|
"SUB normalColor, normalColor, 1.0;\n"
|
|
|
|
// Normalize normal texture
|
|
"DP3 temp, normalColor, normalColor;\n"
|
|
"RSQ invLen, temp.x;\n"
|
|
"MUL normalColor, invLen, normalColor;\n"
|
|
|
|
// Fresenel approximation
|
|
"DP3 trans.w, normalColor, eyeVec;\n"
|
|
"SUB endColor.w, 1.0, trans.w;\n"
|
|
"MAX endColor.w, endColor.w, 0.2;\n" // MAX sets the min? How odd.
|
|
"MIN endColor.w, endColor.w, 0.8;\n" // Leave a LITTLE bit of transparency always
|
|
|
|
// Put the color in the output (TODO: put this in final OP)
|
|
"MOV result.color, endColor;\n"
|
|
|
|
"END\n";
|
|
|
|
|
|
static char vertex_program_distort[] =
|
|
"!!ARBvp1.0\n"
|
|
"OPTION ARB_position_invariant;\n"
|
|
|
|
"PARAM vec = { 1.0, 0.0, 0.0, 1.0 };\n"
|
|
"PARAM dtc = { 0.0, 0.5, 0.0, 1.0 };\n"
|
|
|
|
"TEMP R0, R1, R2;\n"
|
|
|
|
"MOV R0, vec;\n"
|
|
"DP4 R0.z, vertex.position, state.matrix.modelview.row[2];\n"
|
|
|
|
"DP4 R1, R0, state.matrix.projection.row[0];\n"
|
|
"DP4 R2, R0, state.matrix.projection.row[3];\n"
|
|
|
|
// don't let the recip get near zero for polygons that cross the view plane
|
|
"MAX R2, R2, 1.0;\n"
|
|
|
|
"RCP R2, R2.w;\n"
|
|
"MUL R1, R1, R2;\n"
|
|
|
|
// clamp the distance so the deformations don't get too wacky near the view
|
|
"MIN R1, R1, 0.02;\n"
|
|
|
|
"MOV result.texcoord[0], dtc;\n"
|
|
"DP4 result.texcoord[0].x, vertex.texcoord[0], state.matrix.texture[0].row[0];\n"
|
|
"DP4 result.texcoord[0].y, vertex.texcoord[0], state.matrix.texture[0].row[1];\n"
|
|
|
|
"MOV result.texcoord[2], dtc;\n"
|
|
"DP4 result.texcoord[2].x, vertex.texcoord[2], state.matrix.texture[2].row[0];\n"
|
|
"DP4 result.texcoord[2].y, vertex.texcoord[2], state.matrix.texture[2].row[1];\n"
|
|
|
|
"MUL result.texcoord[3], R1, program.local[0];\n"
|
|
|
|
"MOV result.color, vertex.color;\n"
|
|
|
|
"END\n";
|
|
|
|
|
|
/*
|
|
=============================================================================
|
|
|
|
PROGRAM MANAGEMENT
|
|
|
|
=============================================================================
|
|
*/
|
|
|
|
static char *fragment_progs[NUM_FRAGMENT_PROGRAM] =
|
|
{
|
|
fragment_program_heathazemask,
|
|
fragment_program_warp,
|
|
fragment_program_warp_lightmap,
|
|
fragment_program_water_distort
|
|
};
|
|
|
|
static char *vertex_progs[NUM_VERTEX_PROGRAM] =
|
|
{
|
|
vertex_program_distort
|
|
};
|
|
|
|
GLuint fragment_programs[NUM_FRAGMENT_PROGRAM];
|
|
GLuint vertex_programs[NUM_VERTEX_PROGRAM];
|
|
|
|
|
|
/*
|
|
=============
|
|
R_Compile_ARB_Programs
|
|
=============
|
|
*/
|
|
void R_Compile_ARB_Programs (void)
|
|
{
|
|
int i, error_pos;
|
|
const char *errors;
|
|
|
|
if (!glConfig.arb_fragment_program) // not supported/enabled
|
|
return;
|
|
|
|
// fragment programs
|
|
qglGenProgramsARB(NUM_FRAGMENT_PROGRAM, &fragment_programs[0]);
|
|
for (i = 0; i < NUM_FRAGMENT_PROGRAM; i++)
|
|
{
|
|
qglBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, fragment_programs[i]);
|
|
qglProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
|
|
strlen(fragment_progs[i]), fragment_progs[i]);
|
|
qglGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &error_pos);
|
|
if (error_pos != -1)
|
|
{
|
|
errors = qglGetString(GL_PROGRAM_ERROR_STRING_ARB);
|
|
VID_Printf (PRINT_ALL, S_COLOR_RED"FragmentProgram error at position %d in shader %d\nARB_ERROR: %s\n",
|
|
error_pos, fragment_programs[i], errors);
|
|
qglDeleteProgramsARB(1, &fragment_programs[i]);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// vertex programs
|
|
if (glConfig.arb_vertex_program)
|
|
{
|
|
qglGenProgramsARB(NUM_VERTEX_PROGRAM, &vertex_programs[0]);
|
|
for (i = 0; i < NUM_VERTEX_PROGRAM; i++)
|
|
{
|
|
qglBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertex_programs[i]);
|
|
qglProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
|
|
strlen(vertex_progs[i]), vertex_progs[i]);
|
|
qglGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &error_pos);
|
|
if (error_pos != -1)
|
|
{
|
|
errors = qglGetString(GL_PROGRAM_ERROR_STRING_ARB);
|
|
VID_Printf (PRINT_ALL, S_COLOR_RED"VertexProgram error at position %d in shader %d\nARB_ERROR: %s\n",
|
|
error_pos, vertex_programs[i], errors);
|
|
qglDeleteProgramsARB(1, &vertex_programs[i]);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
VID_Printf (PRINT_ALL, "...loading ARB programs... succeeded\n");
|
|
}
|
|
|