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