1 /*
2 *------------------------------------------------------------
3 * Copyright(c) 2009-2010 by Digital Media Professionals Inc.
4 * All rights reserved.
5 *------------------------------------------------------------
6 * This source code is the confidential and proprietary
7 * of Digital Media Professionals Inc.
8 *------------------------------------------------------------
9 */
10
11 #include <math.h>
12 #include "Gas.h"
13 #include "Util.h"
14
15 #include <assert.h>
16
17 extern GLuint pAccId;
18 extern GLuint pPostId;
19 extern struct gas_data gas;
20
21 /*
22 * Local definition
23 */
24 #define SHADING_WIDTH nn::gx::DISPLAY0_WIDTH
25 #define SHADING_HEIGHT nn::gx::DISPLAY0_HEIGHT
26 // SHADING_BUFFER uses the display buffer created by demo::RenderSystem.
27 // #define SHADING_BUFFER DISPLAY_BUFFER
28
29 /* buffer id */
30 static struct tagBufID
31 {
32 GLuint acc; /* frame buffer for accumulation */
33 GLuint shading; /* frame buffer for shading */
34 GLuint accColor; /* Color buffer for accumulation */
35 } gasbuf;
36
37 /* texture id */
38 GLuint gastex;
39
40 /* particle pattern file names */
41 static char* particle_files[PARTICLE_PATTERNS] = {PARTICLE_FILES};
42
43 /*=======================================================*/
44 /* buffer initialization */
45 /*=======================================================*/
GasInitialize(GLuint depthBuf)46 void GasInitialize(GLuint depthBuf)
47 {
48 /*
49 * Generate framebuffers and texture for gas rendering
50 */
51
52 /* generation */
53 glGenFramebuffers(1, (GLuint*)&gasbuf.acc);
54 glGenTextures(1, (GLuint*)&gastex);
55 glGenRenderbuffers(1, (GLuint*)&gasbuf.accColor);
56
57 /* set shading buffer
58 * In GAS_CONFIG_SIMPLE case, shading buffer is DISPLAY_BUFFER
59 * and in GAS_CONFIG_OPTIMAL case, shading buffer is accumulation buffer(reused) */
60 // gasbuf.shading = SHADING_BUFFER;
61
62 /*
63 * Initialize accumulation buffer (destination of gas accumulation rendering)
64 * (in GAS_CONFIG_OPTIMAL case, this buffer is reused as a destination of shading)
65 */
66
67 /* initialize renderbuffer for color */
68 glBindRenderbuffer(GL_RENDERBUFFER, gasbuf.accColor);
69 glRenderbufferStorage(GL_RENDERBUFFER, GL_GAS_DMP, GAS_ACC_WIDTH, GAS_ACC_HEIGHT);
70
71 /* Attach renderbuffer to framebuffer */
72 glBindFramebuffer(GL_FRAMEBUFFER, gasbuf.acc);
73 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, gasbuf.accColor);
74
75 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, depthBuf);
76
77 /*
78 * Initialize accumulation pow2 texture area (copy destination of accumulation result or shading result)
79 */
80 glBindTexture(GL_TEXTURE_2D, gastex);
81 glTexImage2D(GL_TEXTURE_2D, 0, GL_GAS_DMP, GAS_TEX_WIDTH, GAS_TEX_HEIGHT, 0, GL_GAS_DMP, GL_UNSIGNED_SHORT, 0);
82 glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
83 glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
84 }
85
86 /*=======================================================*/
87 /* Setup of default gasesous object data structure */
88 /*=======================================================*/
DefaultGasObject(struct gas_data * gas,float * gasColorTable)89 void DefaultGasObject(struct gas_data *gas, float *gasColorTable)
90 {
91 gas->_dela_z = 100.0f;
92 gas->_autoAcc = GL_TRUE;
93 gas->_densMax = 1.0f/6.0f;
94 gas->_lightDirX = 0.5f;
95 gas->_lightDirY = 0.5f;
96
97 gas->_LightXY[0] = 0.0f;
98 gas->_LightXY[1] = 0.3f;
99 gas->_LightXY[2] = 1.0f;
100 gas->_LightXY[3] = 0.0f; /* unsused */
101
102 gas->_LightZ[0] = 0.0f;
103 gas->_LightZ[1] = 1.0f;
104 gas->_LightZ[2] = 0.5f;
105 gas->_LightZ[3] = 1.0f;
106
107 gas->shadingDensitySrc = GL_GAS_DEPTH_DENSITY_DMP; /* GL_GAS_DEPTH_DENSITY_DMP/GL_GAS_PLAIN_DENSITY_DMP */
108 gas->colorLutInput = GL_GAS_DENSITY_DMP; /* GL_GAS_DENSITY_DMP/GL_GAS_LIGHT_FACTOR_DMP */
109
110 float dxt = 1.0f / 127.0f;
111 float xt = 0;
112 for (int i = 0; i < 128; i++)
113 {
114 gas->fogTable[i]= 1.0f - exp(-8.0f * xt);
115 xt += dxt;
116 }
117
118 for (int i = 0; i < 128; i++)
119 {
120 gas->fogTable[128 + i] = gas->fogTable[i + 1] - gas->fogTable[i];
121 }
122
123 gas->fogTable[255] = 0;
124 glGenTextures(1, &gas->CollectionLUT_ID);
125 glGenTextures(1, &gas->FogLut_ID);
126
127 glBindTexture(GL_TEXTURE_COLLECTION_DMP, gas->CollectionLUT_ID);
128 glBindTexture(GL_LUT_TEXTURE0_DMP, gas->FogLut_ID);
129 glTexImage1D(GL_LUT_TEXTURE0_DMP, 0, GL_LUMINANCEF_DMP, 256, 0, GL_LUMINANCEF_DMP, GL_FLOAT, gas->fogTable);
130
131 glGenTextures(3,&gas->gasTransfert_ID[0]);
132
133 SetGasColorTable(gas,gasColorTable);
134
135 float u0 = 0.0f;
136 float v0 = 0.0f;
137
138 float u1 = (GAS_ACC_WIDTH * 1.0f) / (GAS_TEX_WIDTH * 1.0f);
139 float v1 = (GAS_ACC_HEIGHT * 1.0f) / (GAS_TEX_HEIGHT * 1.0f);
140
141 GLfloat tex_unit[8]= {u0, v0, u0, v1, u1, v1, u1, v0};
142
143 GLfloat LX0, LY0, LX1, LY1;
144 LX0 = 0.0f;
145 LY0 = 0.0f;
146 LX1 = gas->_lightDirX;
147 LY1 = gas->_lightDirY;
148 GLfloat vertex_color[16] =
149 {
150 LX0, 0.0f, 0.0f, LY0,
151 LX0, 0.0f, 0.0f, LY1,
152 LX1, 0.0f, 0.0f, LY1,
153 LX1, 0.0f, 0.0f, LY0
154 };
155
156 GLushort _quadIndex[6] = {0, 1, 2, 0, 2, 3};
157 GLfloat vertex_unit[16] =
158 {
159 -1.0f, -1.0f, 0.0f, 1.0f,
160 -1.0f, 1.0f, 0.0f, 1.0f,
161 1.0f, 1.0f, 0.0f, 1.0f,
162 1.0f, -1.0f, 0.0f, 1.0f
163 };
164
165 glGenBuffers(1, &gas->quad_index_ID);
166 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gas->quad_index_ID);
167 glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6*sizeof(GLushort), &_quadIndex, GL_STATIC_DRAW);
168
169 glGenBuffers(1, &gas->quad_vertBuf_ID);
170 glBindBuffer(GL_ARRAY_BUFFER,gas->quad_vertBuf_ID);
171 glBufferData(GL_ARRAY_BUFFER, 16*sizeof(GLfloat), &vertex_unit, GL_STATIC_DRAW);
172
173 glGenBuffers(1, &gas->quad_texBuf_ID);
174 glBindBuffer(GL_ARRAY_BUFFER,gas->quad_texBuf_ID);
175 glBufferData(GL_ARRAY_BUFFER, 8*sizeof(GLfloat), &tex_unit, GL_STATIC_DRAW);
176
177 glGenBuffers(1, &gas->quad_colBuf_ID);
178 glBindBuffer(GL_ARRAY_BUFFER,gas->quad_colBuf_ID);
179 glBufferData(GL_ARRAY_BUFFER, 16*sizeof(GLfloat), &vertex_color, GL_STATIC_DRAW);
180
181 /*
182 * Load particle patterns
183 */
184 glGenTextures(PARTICLE_PATTERNS, &gas->pattern[0]);
185 for (int i = 0; i < PARTICLE_PATTERNS; i++)
186 {
187 bool alpha;
188 glBindTexture(GL_TEXTURE_2D, gas->pattern[i]);
189 glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
190 glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
191 loadTexture(particle_files[i], GL_TEXTURE_2D, 0, alpha);
192 }
193 }
194
195 /*=======================================================*/
196 /* Load Gas color lookup table */
197 /*=======================================================*/
SetGasColorTable(struct gas_data * gas,float * gasColorTable)198 void SetGasColorTable(struct gas_data *gas, float *gasColorTable)
199 {
200 glBindTexture(GL_TEXTURE_COLLECTION_DMP, gas->CollectionLUT_ID);
201 for(int i = 0; i < 8; i++)
202 {
203 gas->RR[i] = gasColorTable[3 * i + 0];
204 gas->GG[i] = gasColorTable[3 * i + 1];
205 gas->BB[i] = gasColorTable[3 * i + 2];
206
207 gas->RR[8 + i] = gasColorTable[3 * (i + 1) + 0] - gasColorTable[3 * i + 0];
208 gas->GG[8 + i] = gasColorTable[3 * (i + 1) + 1] - gasColorTable[3 * i + 1];
209 gas->BB[8 + i] = gasColorTable[3 * (i + 1) + 2] - gasColorTable[3 * i + 2];
210 }
211 gas->RR[15] = 0.0f;
212 gas->GG[15] = 0.0f;
213 gas->BB[15] = 0.0f;
214
215 glBindTexture(GL_LUT_TEXTURE1_DMP, gas->gasTransfert_ID[0]);
216 glTexImage1D(GL_LUT_TEXTURE1_DMP, 0, GL_LUMINANCEF_DMP, 16, 0, GL_LUMINANCEF_DMP, GL_FLOAT, gas->RR);
217
218 glBindTexture(GL_LUT_TEXTURE2_DMP, gas->gasTransfert_ID[1]);
219 glTexImage1D(GL_LUT_TEXTURE2_DMP, 0, GL_LUMINANCEF_DMP, 16, 0, GL_LUMINANCEF_DMP, GL_FLOAT, gas->GG);
220
221 glBindTexture(GL_LUT_TEXTURE3_DMP, gas->gasTransfert_ID[2]);
222 glTexImage1D(GL_LUT_TEXTURE3_DMP, 0, GL_LUMINANCEF_DMP, 16, 0, GL_LUMINANCEF_DMP, GL_FLOAT, gas->BB);
223 }
224
SetGasAccumulationUniform(void)225 void SetGasAccumulationUniform(void)
226 {
227 glUseProgram(pAccId);
228 glUniform1i(glGetUniformLocation(pAccId, "dmp_Texture[0].samplerType"), GL_TEXTURE_2D);
229 glUniform1i(glGetUniformLocation(pAccId, "dmp_TexEnv[0].combineRgb"), GL_MODULATE);
230 glUniform1i(glGetUniformLocation(pAccId, "dmp_TexEnv[0].combineAlpha"), GL_REPLACE);
231 glUniform3i(glGetUniformLocation(pAccId, "dmp_TexEnv[0].operandRgb"), GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_COLOR);
232 glUniform3i(glGetUniformLocation(pAccId, "dmp_TexEnv[0].operandAlpha"), GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA);
233 glUniform3i(glGetUniformLocation(pAccId, "dmp_TexEnv[0].srcRgb"), GL_TEXTURE0, GL_PRIMARY_COLOR, GL_PRIMARY_COLOR);
234 glUniform3i(glGetUniformLocation(pAccId, "dmp_TexEnv[0].srcAlpha"), GL_TEXTURE0, GL_PRIMARY_COLOR, GL_PRIMARY_COLOR);
235
236 /* Set the mode for the per fragment operation (gas accumulation mode) */
237 glUniform1i(glGetUniformLocation(pAccId, "dmp_FragOperation.mode"), GL_FRAGOP_MODE_GAS_ACC_DMP);
238
239 /* Set this value to control the accuracy of z intersection of surface and gaseous objects */
240 glUniform1f(glGetUniformLocation(pAccId, "dmp_Gas.deltaZ"),gas._dela_z);
241
242 glUniform1i(glGetUniformLocation(pAccId, "dmp_Fog.mode"), GL_FALSE);
243
244 float wh[2] = {0};
245 wh[0] = 1.f / (float)GAS_ACC_WIDTH;
246 wh[1] = 1.f / (float)GAS_ACC_HEIGHT;
247 glUniform2fv ( glGetUniformLocation ( pAccId, "dmp_Point.viewport" ), 1, wh ) ;
248 glUniform1i(glGetUniformLocation(pAccId, "dmp_Point.distanceAttenuation"), GL_TRUE);
249
250 }
251
SetGasShadingUniform(void)252 void SetGasShadingUniform(void)
253 {
254 glUseProgram(pPostId);
255
256 /* Setup blending unit #0
257 * r component of primary color has the influence of LIGHT_X and LIGHT_Y
258 * this output is transfered to FOG unit when FOG_MODE is set to GAS_DMP */
259 glUniform1i(glGetUniformLocation(pPostId, "dmp_Texture[0].samplerType"), GL_TEXTURE_2D);
260 glUniform1i(glGetUniformLocation(pPostId, "dmp_TexEnv[0].combineRgb"), GL_REPLACE);
261 glUniform1i(glGetUniformLocation(pPostId, "dmp_TexEnv[0].combineAlpha"), GL_ADD);
262 glUniform3i(glGetUniformLocation(pPostId, "dmp_TexEnv[0].operandRgb"), GL_SRC_COLOR, GL_SRC_ALPHA, GL_SRC_COLOR);
263 glUniform3i(glGetUniformLocation(pPostId, "dmp_TexEnv[0].operandAlpha"), GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA);
264 glUniform3i(glGetUniformLocation(pPostId, "dmp_TexEnv[0].srcRgb"), GL_PRIMARY_COLOR, GL_PRIMARY_COLOR, GL_PRIMARY_COLOR);
265 glUniform3i(glGetUniformLocation(pPostId, "dmp_TexEnv[0].srcAlpha"), GL_PRIMARY_COLOR, GL_PRIMARY_COLOR, GL_PRIMARY_COLOR);
266
267 /* Setup blending unit #5
268 * This is HW requirement. See specification document for more details
269 */
270 glUniform3i(glGetUniformLocation(pPostId, "dmp_TexEnv[5].srcRgb"), GL_PREVIOUS, GL_PREVIOUS, GL_TEXTURE0);
271 glUniform3i(glGetUniformLocation(pPostId, "dmp_TexEnv[5].srcAlpha"), GL_PREVIOUS, GL_PREVIOUS, GL_TEXTURE0);
272
273 /* setup of gas shading */
274 glUniform1i(glGetUniformLocation(pPostId, "dmp_Fog.sampler"), 0);
275 glUniform1i(glGetUniformLocation(pPostId, "dmp_Fog.mode"), GL_GAS_DMP);
276 glUniform1i(glGetUniformLocation(pPostId, "dmp_Gas.autoAcc"), gas._autoAcc);
277 glUniform1i(glGetUniformLocation(pPostId, "dmp_Gas.samplerTR"), 1);
278 glUniform1i(glGetUniformLocation(pPostId, "dmp_Gas.samplerTG"), 2);
279 glUniform1i(glGetUniformLocation(pPostId, "dmp_Gas.samplerTB"), 3);
280 glUniform1i(glGetUniformLocation(pPostId, "dmp_Gas.shadingDensitySrc"), gas.shadingDensitySrc);
281 glUniform1i(glGetUniformLocation(pPostId, "dmp_Gas.colorLutInput"), gas.colorLutInput);
282 glUniform1f(glGetUniformLocation(pPostId, "dmp_Gas.accMax"), gas._densMax);
283 glUniform4fv(glGetUniformLocation(pPostId, "dmp_Gas.lightZ"), 1, gas._LightZ);
284 glUniform3fv(glGetUniformLocation(pPostId, "dmp_Gas.lightXY"), 1, gas._LightXY);
285
286 glUniform1i(glGetUniformLocation(pPostId, "dmp_FragOperation.mode"), GL_FRAGOP_MODE_GL_DMP);
287 }
288
289 /*=======================================================*/
290 /* accumulation pass */
291 /*=======================================================*/
GasAccumulation()292 void GasAccumulation()
293 {
294 /*
295 * In accumulation pass, particles are accumulated into gas accumulation buffer as
296 * density information. This buffer is 'gasbuf.acc' in this sample. In GAS_CONFIG_SIMPLE
297 * configuration, this buffer is exactly same size as DISPLAY_BUFFER (possible not to be
298 * pow2 size). So, for next pass, the accumulation result should be copy to pow2 size texture.
299 */
300
301 /* Bind accumulation buffer as a rendering target */
302 glBindFramebuffer(GL_FRAMEBUFFER, gasbuf.acc);
303 /* use gas accumulation related program */
304 glUseProgram(pAccId);
305 /* Set viewport */
306 glViewport(0, 0, GAS_ACC_WIDTH, GAS_ACC_HEIGHT);
307 /* Clear the buffer content (only color!) */
308 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
309 glClear(GL_COLOR_BUFFER_BIT);
310
311
312 /* misc state */
313 glDisable(GL_DEPTH_TEST);
314 glDepthFunc(GL_LESS);
315
316 glDisable(GL_CULL_FACE);
317 glFrontFace(GL_CCW);
318 glCullFace(GL_BACK);
319
320 /* texture pattern binding */
321 /* assuming only 1 pattern */
322 glActiveTexture(GL_TEXTURE0);
323 glBindTexture(GL_TEXTURE_2D, gas.pattern[0]);
324
325 /*
326 * Setup buffer
327 */
328 glEnableVertexAttribArray(0);
329 glEnableVertexAttribArray(1);
330 glEnableVertexAttribArray(2);
331
332 glBindBuffer(GL_ARRAY_BUFFER, gas.gasgeo_center_ID);
333 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
334
335 glBindBuffer(GL_ARRAY_BUFFER, gas.gasgeo_density_ID);
336 glVertexAttribPointer(1, 1, GL_FLOAT, GL_FALSE, 0, 0);
337
338 glBindBuffer(GL_ARRAY_BUFFER, gas.gasgeo_size_ID);
339 glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE, 0, 0);
340
341
342 glDrawArrays(GL_GEOMETRY_PRIMITIVE_DMP, 0,gas.gasgeo_size);
343
344 glDisableVertexAttribArray(0);
345 glDisableVertexAttribArray(1);
346 glDisableVertexAttribArray(2);
347
348 glFinish();
349
350 /*
351 * Copy accumulation result to the texture buffer
352 */
353 glBindTexture(GL_TEXTURE_2D, gastex);
354 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, GAS_ACC_WIDTH, GAS_ACC_HEIGHT);
355 glFinish();
356
357 glBindTexture(GL_TEXTURE_2D, 0);
358 }
359
360 /*=======================================================*/
361 /* shading pass */
362 /*=======================================================*/
GasShading(void)363 void GasShading(void)
364 {
365 /*
366 * In shading pass, shaded gaseous image is blended to DISPLAY_BUFFER.
367 * Accumulated density information is used as a gas texture.
368 * Note that in GAS_CONFIG_OPTIMAL case, DISPLAY_BUFFER is defferent size
369 * from gas texture and PICA does not support filter for gas format texture.
370 * So gaseous shaded image is rendered to another buffer and then blend to
371 * DIPLAY_BUFFER.
372 */
373
374 /* Bind shading buffer and set viewport
375 * In GAS_CONFIG_SIMPLE case, shading buffer is DISPLAY_BUFFER
376 * and in GAS_CONFIG_OPTIMAL case, shading buffer is accumulation buffer(reused) */
377 // glBindFramebuffer(GL_FRAMEBUFFER, gasbuf.shading);
378 // glViewport(0, 0, SHADING_WIDTH, SHADING_HEIGHT);
379
380 /* use gas accumulation related program */
381 glUseProgram(pPostId);
382
383 /* Bind gas texture (accumulation result) */
384 glActiveTexture(GL_TEXTURE0);
385 glBindTexture(GL_TEXTURE_2D, gastex);
386 /*
387 * misc settings
388 */
389 glEnable(GL_BLEND);
390 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
391 glDisable(GL_DEPTH_TEST);
392 glDepthMask(0);
393
394 glBindTexture(GL_TEXTURE_COLLECTION_DMP, gas.CollectionLUT_ID);
395 glBindTexture(GL_TEXTURE_2D, gastex);
396
397 glEnableVertexAttribArray(0);
398 glEnableVertexAttribArray(1);
399 glEnableVertexAttribArray(2);
400
401 glBindBuffer(GL_ARRAY_BUFFER, gas.quad_vertBuf_ID);
402 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
403
404 glBindBuffer(GL_ARRAY_BUFFER, gas.quad_texBuf_ID);
405 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
406
407 glBindBuffer(GL_ARRAY_BUFFER, gas.quad_colBuf_ID);
408 glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, 0, 0);
409
410 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gas.quad_index_ID);
411 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);
412
413 glDisableVertexAttribArray(0);
414 glDisableVertexAttribArray(1);
415 glDisableVertexAttribArray(2);
416
417 glDisable(GL_BLEND);
418 glEnable(GL_DEPTH_TEST);
419 glDepthFunc(GL_LESS);
420
421 glDisable(GL_CULL_FACE);
422 glFrontFace(GL_CCW);
423 glCullFace(GL_BACK);
424 }
425
426