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