forked from JACoders/OpenJK
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtr_arb.cpp
192 lines (173 loc) · 7.8 KB
/
tr_arb.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
/*
===========================================================================
Copyright (C) 2000 - 2013, Raven Software, Inc.
Copyright (C) 2001 - 2013, Activision, Inc.
Copyright (C) 2013 - 2015, OpenJK contributors
This file is part of the OpenJK source code.
OpenJK is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation.
This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
===========================================================================
*/
// tr_glow.c -- this file deals with the arb shaders for dynamic glow
#include "tr_local.h"
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Vertex and Pixel Shader definitions. - AReis
/***********************************************************************************************************/
// This vertex shader basically passes through most values and calculates no lighting. The only
// unusual thing it does is add the inputed texel offsets to all four texture units (this allows
// nearest neighbor pixel peeking).
const unsigned char g_strGlowVShaderARB[] =
{
"!!ARBvp1.0\
\
# Input.\n\
ATTRIB iPos = vertex.position;\
ATTRIB iColor = vertex.color;\
ATTRIB iTex0 = vertex.texcoord[0];\
ATTRIB iTex1 = vertex.texcoord[1];\
ATTRIB iTex2 = vertex.texcoord[2];\
ATTRIB iTex3 = vertex.texcoord[3];\
\
# Output.\n\
OUTPUT oPos = result.position;\
OUTPUT oColor = result.color;\
OUTPUT oTex0 = result.texcoord[0];\
OUTPUT oTex1 = result.texcoord[1];\
OUTPUT oTex2 = result.texcoord[2];\
OUTPUT oTex3 = result.texcoord[3];\
\
# Constants.\n\
PARAM ModelViewProj[4]= { state.matrix.mvp };\
PARAM TexelOffset0 = program.env[0];\
PARAM TexelOffset1 = program.env[1];\
PARAM TexelOffset2 = program.env[2];\
PARAM TexelOffset3 = program.env[3];\
\
# Main.\n\
DP4 oPos.x, ModelViewProj[0], iPos;\
DP4 oPos.y, ModelViewProj[1], iPos;\
DP4 oPos.z, ModelViewProj[2], iPos;\
DP4 oPos.w, ModelViewProj[3], iPos;\
MOV oColor, iColor;\
# Notice the optimization of using one texture coord instead of all four.\n\
ADD oTex0, iTex0, TexelOffset0;\
ADD oTex1, iTex0, TexelOffset1;\
ADD oTex2, iTex0, TexelOffset2;\
ADD oTex3, iTex0, TexelOffset3;\
\
END"
};
// This Pixel Shader loads four texture units and adds them all together (with a modifier
// multiplied to each in the process). The final output is r0 = t0 + t1 + t2 + t3.
const unsigned char g_strGlowPShaderARB[] =
{
"!!ARBfp1.0\
\
# Input.\n\
ATTRIB iColor = fragment.color.primary;\
\
# Output.\n\
OUTPUT oColor = result.color;\
\
# Constants.\n\
PARAM Weight = program.env[0];\
TEMP t0;\
TEMP t1;\
TEMP t2;\
TEMP t3;\
TEMP r0;\
\
# Main.\n\
TEX t0, fragment.texcoord[0], texture[0], RECT;\
TEX t1, fragment.texcoord[1], texture[1], RECT;\
TEX t2, fragment.texcoord[2], texture[2], RECT;\
TEX t3, fragment.texcoord[3], texture[3], RECT;\
\
MUL r0, t0, Weight;\
MAD r0, t1, Weight, r0;\
MAD r0, t2, Weight, r0;\
MAD r0, t3, Weight, r0;\
\
MOV oColor, r0;\
\
END"
};
/***********************************************************************************************************/
#define GL_PROGRAM_ERROR_STRING_ARB 0x8874
#define GL_PROGRAM_ERROR_POSITION_ARB 0x864B
void ARB_InitGlowShaders(void) {
// Allocate and Load the global 'Glow' Vertex Program. - AReis
if ( qglGenProgramsARB )
{
qglGenProgramsARB( 1, &tr.glowVShader );
qglBindProgramARB( GL_VERTEX_PROGRAM_ARB, tr.glowVShader );
qglProgramStringARB( GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, ( GLsizei ) strlen( ( char * ) g_strGlowVShaderARB ), g_strGlowVShaderARB );
// const GLubyte *strErr = qglGetString( GL_PROGRAM_ERROR_STRING_ARB );
int iErrPos = 0;
qglGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &iErrPos );
assert( iErrPos == -1 );
}
// NOTE: I make an assumption here. If you have (current) nvidia hardware, you obviously support register combiners instead of fragment
// programs, so use those. The problem with this is that nv30 WILL support fragment shaders, breaking this logic. The good thing is that
// if you always ask for regcoms before fragment shaders, you'll always just use regcoms (problem solved... for now). - AReis
// Load Pixel Shaders (either regcoms or fragprogs).
if ( qglCombinerParameteriNV )
{
// The purpose of this regcom is to blend all the pixels together from the 4 texture units, but with their
// texture coordinates offset by 1 (or more) texels, effectively letting us blend adjoining pixels. The weight is
// used to either strengthen or weaken the pixel intensity. The more it diffuses (the higher the radius of the glow),
// the higher the intensity should be for a noticable effect.
// Regcom result is: ( tex1 * fBlurWeight ) + ( tex2 * fBlurWeight ) + ( tex2 * fBlurWeight ) + ( tex2 * fBlurWeight )
// VV guys, this is the pixel shader you would use instead :-)
/*
// c0 is the blur weight.
ps 1.1
tex t0
tex t1
tex t2
tex t3
mul r0, c0, t0;
madd r0, c0, t1, r0;
madd r0, c0, t2, r0;
madd r0, c0, t3, r0;
*/
tr.glowPShader = qglGenLists( 1 );
qglNewList( tr.glowPShader, GL_COMPILE );
qglCombinerParameteriNV( GL_NUM_GENERAL_COMBINERS_NV, 2 );
// spare0 = fBlend * tex0 + fBlend * tex1.
qglCombinerInputNV( GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_A_NV, GL_TEXTURE0_ARB, GL_UNSIGNED_IDENTITY_NV, GL_RGB );
qglCombinerInputNV( GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_B_NV, GL_CONSTANT_COLOR0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB );
qglCombinerInputNV( GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_C_NV, GL_TEXTURE1_ARB, GL_UNSIGNED_IDENTITY_NV, GL_RGB );
qglCombinerInputNV( GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_D_NV, GL_CONSTANT_COLOR0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB );
qglCombinerOutputNV( GL_COMBINER0_NV, GL_RGB, GL_DISCARD_NV, GL_DISCARD_NV, GL_SPARE0_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE );
// spare1 = fBlend * tex2 + fBlend * tex3.
qglCombinerInputNV( GL_COMBINER1_NV, GL_RGB, GL_VARIABLE_A_NV, GL_TEXTURE2_ARB, GL_UNSIGNED_IDENTITY_NV, GL_RGB );
qglCombinerInputNV( GL_COMBINER1_NV, GL_RGB, GL_VARIABLE_B_NV, GL_CONSTANT_COLOR0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB );
qglCombinerInputNV( GL_COMBINER1_NV, GL_RGB, GL_VARIABLE_C_NV, GL_TEXTURE3_ARB, GL_UNSIGNED_IDENTITY_NV, GL_RGB );
qglCombinerInputNV( GL_COMBINER1_NV, GL_RGB, GL_VARIABLE_D_NV, GL_CONSTANT_COLOR0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB );
qglCombinerOutputNV( GL_COMBINER1_NV, GL_RGB, GL_DISCARD_NV, GL_DISCARD_NV, GL_SPARE1_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE );
// ( A * B ) + ( ( 1 - A ) * C ) + D = ( spare0 * 1 ) + ( ( 1 - spare0 ) * 0 ) + spare1 == spare0 + spare1.
qglFinalCombinerInputNV( GL_VARIABLE_A_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB );
qglFinalCombinerInputNV( GL_VARIABLE_B_NV, GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_RGB );
qglFinalCombinerInputNV( GL_VARIABLE_C_NV, GL_ZERO, GL_UNSIGNED_IDENTITY_NV, GL_RGB );
qglFinalCombinerInputNV( GL_VARIABLE_D_NV, GL_SPARE1_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB );
qglEndList();
}
else if ( qglGenProgramsARB )
{
qglGenProgramsARB( 1, &tr.glowPShader );
qglBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, tr.glowPShader );
qglProgramStringARB( GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, ( GLsizei ) strlen( ( char * ) g_strGlowPShaderARB ), g_strGlowPShaderARB );
// const GLubyte *strErr = qglGetString( GL_PROGRAM_ERROR_STRING_ARB );
int iErrPos = 0;
qglGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &iErrPos );
assert( iErrPos == -1 );
}
}