/*---------------------------------------------------------------------------* Project: Horizon File: GasCessna.cpp Copyright (C)2009-2012 Nintendo Co., Ltd. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Rev: 47228 $ *---------------------------------------------------------------------------*/ /* *------------------------------------------------------------ * Copyright(c) 2009-2010 by Digital Media Professionals Inc. * All rights reserved. *------------------------------------------------------------ * This source code is the confidential and proprietary * of Digital Media Professionals Inc. *------------------------------------------------------------ */ #include #include #include #include #include #include #include "demo.h" #include "Util.h" #include "Loader.h" #include #include #include "Gas.h" #include "Memory.h" extern GLfloat particleData[]; extern float gasColorTable[6][24]; #define NUM_COLOR_SAMPLE 6 /* program id */ GLuint pGeoId; /* for normal geometry */ GLuint pAccId; /* for gas accumulation pass */ GLuint pPostId; /* for gas shading/post synthesis pass */ /* Standard object (triangles, not gaseous object) */ dat_t cessna; struct gas_data gas; /* Standard object (triangles, not gaseous object) */ GLuint lutids[2]; static struct tagParticeInfo { GLint cnt; /* particle count */ GLfloat* position; /* particle position array */ GLfloat* size; /* particle size array */ GLfloat* density; /* particle density array */ } prtclinfo; /* ExpHeap for app. */ nn::fnd::ExpHeap s_AppHeap; uptr s_HeapForGx; uptr s_HeapForMalloc; const u32 s_GxHeapSize = 0x400000; const u32 s_HeapSize = 0x200000; demo::RenderSystem s_RenderSystem; /*=======================================================*/ /* Static function declaration */ /*=======================================================*/ static int DrawFrame(void); /*=======================================================*/ /* initialization */ /*=======================================================*/ static void Initialize(void) { s_AppHeap.Initialize(nn::os::GetDeviceMemoryAddress(), nn::os::GetDeviceMemorySize() ); s_HeapForGx = reinterpret_cast(s_AppHeap.Allocate(s_GxHeapSize)); /* Initialize display */ s_RenderSystem.Initialize(s_HeapForGx, s_GxHeapSize); /* Create heap for malloc*/ s_HeapForMalloc = reinterpret_cast(s_AppHeap.Allocate(s_HeapSize)); setMemoryHeap(s_HeapForMalloc, s_HeapSize); /* Initialization for gas */ GLuint depthStencilBufferId = s_RenderSystem.GetRenderBufferObjectId(NN_GX_DISPLAY0, GL_DEPTH_STENCIL_ATTACHMENT); GasInitialize(depthStencilBufferId); } /*=======================================================*/ /* finalization */ /*=======================================================*/ void GasFinalize(void) { free(prtclinfo.position); free(prtclinfo.size); free(prtclinfo.density); } static void UnloadObjects(void) { unloadDAT(&cessna); return; } /*=======================================================*/ /* initialization of the geometry and gaseous object */ /*=======================================================*/ static void SceneObjectInitialize(void) { /* Load object (non-gaseous object) */ loadDAT("rom:/resources/cessna.dat", &cessna); /* Load Gaseous object */ DefaultGasObject(&gas, gasColorTable[0]); /* Define the gaseous object geometry */ /* A simple quad in this sample */ GLfloat* p = &particleData[1]; prtclinfo.cnt = (GLuint)particleData[0]; prtclinfo.position = (GLfloat*)malloc(sizeof(GLfloat) * prtclinfo.cnt * 4); prtclinfo.size = (GLfloat*)malloc(sizeof(GLfloat) * prtclinfo.cnt); prtclinfo.density = (GLfloat*)malloc(sizeof(GLfloat) * prtclinfo.cnt); for (int i = 0; i < prtclinfo.cnt; i++) { prtclinfo.position[i*4+0] = *p++ / 1.0f; /* x */ prtclinfo.position[i*4+1] = *p++ / 1.0f; /* y */ prtclinfo.position[i*4+2] = *p++ / 1.0f; /* z */ prtclinfo.position[i*4+3] = 1.0f; /* w */ prtclinfo.size[i] = *p++ / 1.0f; /* size */ prtclinfo.density[i] = *p++ * 5.f; /* density */ /* Adjust particle size based on accumulation buffer size */ prtclinfo.size[i] *= GAS_ACC_HEIGHT * 2; } glGenBuffers(1, &gas.gasgeo_center_ID); glGenBuffers(1, &gas.gasgeo_density_ID); glGenBuffers(1, &gas.gasgeo_size_ID); glGenBuffers(1, &gas.gasgeo_ind_ID); glBindBuffer(GL_ARRAY_BUFFER, gas.gasgeo_center_ID); glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 4 * prtclinfo.cnt, &prtclinfo.position[0], GL_STATIC_DRAW); gas.gasgeo_size = 6; glBindBuffer(GL_ARRAY_BUFFER, gas.gasgeo_size_ID); glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 1 *prtclinfo.cnt , &prtclinfo.size[0], GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, gas.gasgeo_density_ID); glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 1 * prtclinfo.cnt, &prtclinfo.density[0], GL_STATIC_DRAW); gas.gasgeo_size = prtclinfo.cnt; SetGasAccumulationUniform(); SetGasShadingUniform(); } /*=======================================================*/ /* Initialize material used for the geometry */ /*=======================================================*/ void SetGeoMaterial(GLuint pgid) { GLfloat lut[512]; int j; glGenTextures(2, lutids); glBindTexture(GL_TEXTURE_COLLECTION_DMP, lutids[0]); memset(lut, 0, sizeof(lut)); for (j = 0; j < 256; j++) lut[j] = pow((float)j/256.0f, 15.f); for (j = 0; j < 255; j++) lut[j + 256] = lut[j+1] - lut[j]; lut[255 + 256] = 1.f - lut[255]; glBindTexture(GL_LUT_TEXTURE0_DMP, lutids[1]); glTexImage1D(GL_LUT_TEXTURE0_DMP, 0, GL_LUMINANCEF_DMP, 512, 0, GL_LUMINANCEF_DMP, GL_FLOAT, lut); glUniform1i(glGetUniformLocation(pgid, "dmp_FragmentMaterial.samplerD0"), 0); glUniform1i(glGetUniformLocation(pgid, "dmp_FragmentLighting.enabled"), GL_TRUE); glUniform1i(glGetUniformLocation(pgid, "dmp_FragmentLightSource[0].enabled"), GL_TRUE); glUniform1i(glGetUniformLocation(pgid, "dmp_LightEnv.absLutInputD0"), GL_TRUE); glUniform1i(glGetUniformLocation(pgid, "dmp_LightEnv.lutInputD0"), GL_LIGHT_ENV_NH_DMP); glUniform1i(glGetUniformLocation(pgid, "dmp_FragmentLightSource[0].geomFactor0"), GL_FALSE); glUniform1i(glGetUniformLocation(pgid, "dmp_FragmentLightSource[0].geomFactor1"), GL_FALSE); glUniform1i(glGetUniformLocation(pgid, "dmp_FragmentLightSource[0].twoSideDiffuse"), GL_FALSE); glUniform1i(glGetUniformLocation(pgid, "dmp_LightEnv.lutEnabledRefl"), GL_FALSE); glUniform1i(glGetUniformLocation(pgid, "dmp_LightEnv.clampHighlights"), GL_FALSE); glUniform1f(glGetUniformLocation(pgid, "dmp_LightEnv.lutScaleD0"), 1.f); glUniform1i(glGetUniformLocation(pgid, "dmp_LightEnv.config"), GL_LIGHT_ENV_LAYER_CONFIG0_DMP); glUniform1i(glGetUniformLocation(pgid, "dmp_LightEnv.lutEnabledD0"), GL_TRUE); glUniform1i(glGetUniformLocation(pgid, "dmp_LightEnv.bumpMode"), GL_LIGHT_ENV_BUMP_NOT_USED_DMP); GLfloat white[] = {1.0f, 1.0f, 1.0f, 1.0f}; GLfloat black[] = {0.0f, 0.0f, 0.0f, 0.0f}; GLfloat green[] = {0.2f, 0.7f, 0.4f, 1.0f}; glUniform4fv(glGetUniformLocation(pgid, "dmp_FragmentMaterial.specular1"), 1, black); glUniform4fv(glGetUniformLocation(pgid, "dmp_FragmentLightSource[0].diffuse"), 1, white); glUniform4fv(glGetUniformLocation(pgid, "dmp_FragmentLightSource[0].specular0"), 1, white); glUniform4fv(glGetUniformLocation(pgid, "dmp_FragmentLightSource[0].specular1"), 1, black); glUniform4fv(glGetUniformLocation(pgid, "dmp_FragmentMaterial.diffuse"), 1, green); glUniform4fv(glGetUniformLocation(pgid, "dmp_FragmentMaterial.specular0"), 1,white); glUniform4fv(glGetUniformLocation(pgid, "dmp_FragmentMaterial.ambient"), 1, black); glUniform1i(glGetUniformLocation(pgid, "dmp_Texture[0].samplerType"), GL_FALSE); glUniform1i(glGetUniformLocation(pgid, "dmp_TexEnv[0].combineRgb"), GL_ADD); glUniform1i(glGetUniformLocation(pgid, "dmp_TexEnv[0].combineAlpha"), GL_REPLACE); glUniform3i(glGetUniformLocation(pgid, "dmp_TexEnv[0].operandRgb"), GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_COLOR); glUniform3i(glGetUniformLocation(pgid, "dmp_TexEnv[0].operandAlpha"), GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA); glUniform3i(glGetUniformLocation(pgid, "dmp_TexEnv[0].srcRgb"), GL_FRAGMENT_PRIMARY_COLOR_DMP, GL_FRAGMENT_SECONDARY_COLOR_DMP, GL_CONSTANT); glUniform1i(glGetUniformLocation(pgid, "dmp_Texture[1].samplerType"), GL_FALSE); glUniform1i(glGetUniformLocation(pgid, "dmp_TexEnv[1].combineRgb"), GL_REPLACE); glUniform1i(glGetUniformLocation(pgid, "dmp_TexEnv[1].combineAlpha"), GL_REPLACE); glUniform3i(glGetUniformLocation(pgid, "dmp_TexEnv[1].operandRgb"), GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_COLOR); glUniform3i(glGetUniformLocation(pgid, "dmp_TexEnv[1].srcRgb"), GL_PREVIOUS, GL_PREVIOUS, GL_PREVIOUS); } /*=======================================================*/ /* Initialize shaders */ /*=======================================================*/ int ShaderInitialize(void) { GLuint shaders[4] ; shaders[0] = glCreateShader(GL_VERTEX_SHADER); shaders[1] = glCreateShader(GL_VERTEX_SHADER); shaders[2] = glCreateShader(GL_VERTEX_SHADER); shaders[3] = glCreateShader(GL_GEOMETRY_SHADER_DMP); nn::fs::FileReader file(L"rom:/shader.shbin"); size_t fileSize = file.GetSize(); void* buf = s_AppHeap.Allocate(fileSize); s32 read = file.Read(buf, fileSize); glShaderBinary(4, shaders, GL_PLATFORM_BINARY_DMP, buf, read); file.Finalize(); s_AppHeap.Free(buf); pGeoId = glCreateProgram(); glAttachShader(pGeoId, shaders[0]); glAttachShader(pGeoId, GL_DMP_FRAGMENT_SHADER_DMP); glBindAttribLocation(pGeoId, 0, "aPosition"); glBindAttribLocation(pGeoId, 1, "aNormal"); glLinkProgram(pGeoId); glValidateProgram(pGeoId); glUseProgram(pGeoId); SetGeoMaterial(pGeoId); pAccId = glCreateProgram(); glAttachShader(pAccId, shaders[1]); glAttachShader(pAccId, shaders[3]); glAttachShader(pAccId, GL_DMP_FRAGMENT_SHADER_DMP); glBindAttribLocation(pAccId, 0, "aPosition"); glBindAttribLocation(pAccId, 1, "aColor"); glBindAttribLocation(pAccId, 2, "aPointSize"); glLinkProgram(pAccId); glValidateProgram(pAccId); glUseProgram(pAccId); pPostId = glCreateProgram(); glAttachShader(pPostId, shaders[2]); glAttachShader(pPostId, GL_DMP_FRAGMENT_SHADER_DMP); glBindAttribLocation(pPostId, 0, "aPosition"); glBindAttribLocation(pPostId, 1, "aTexCoord"); glBindAttribLocation(pPostId, 2, "aColor"); glLinkProgram(pPostId); glValidateProgram(pPostId); glUseProgram(pPostId); return 0; } /*=======================================================*/ /* draw object */ /*=======================================================*/ static void DrawObject(void) { /* This function draws only one quadrangle. */ glUseProgram(pGeoId); glClearColor(0.2f, 0.4f, 0.7f, 1.0f); glClearDepthf(1.f); /* Set fragment operation mode to GL_FRAGOP_MODE_GL_DMP */ glUniform1i(glGetUniformLocation(pGeoId, "dmp_FragOperation.mode"), GL_FRAGOP_MODE_GL_DMP); /* * Miscellaneous settings */ glDisable(GL_BLEND); glEnable(GL_DEPTH_TEST); glDepthMask(GL_TRUE); glDepthFunc(GL_LEQUAL); glDisable(GL_CULL_FACE); glFrontFace(GL_CCW); glCullFace(GL_BACK); glEnableVertexAttribArray(0); /* enable position */ glEnableVertexAttribArray(1); /* disable texture coordinate */ for (int i = 0; i < cessna.obj_num; i++) { glBindBuffer(GL_ARRAY_BUFFER, cessna.posVB); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)cessna.obj[i].vtx_offset); glBindBuffer(GL_ARRAY_BUFFER, cessna.normVB); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void*)cessna.obj[i].nrm_offset); for (unsigned j = cessna.obj[i].patch_offset; j < cessna.obj[i].patch_size + cessna.obj[i].patch_offset; j++) { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cessna.idxVB); glDrawElements(GL_TRIANGLES, cessna.patch[j].elm_size, GL_UNSIGNED_SHORT, (GLvoid*)(cessna.patch[j].elm_offset + cessna.obj[i].elm_offset)); } } /* * Finalization */ glDisableVertexAttribArray(0); glDisableVertexAttribArray(1); } /*=======================================================*/ /* draw frame */ /*=======================================================*/ static int DrawFrame(void) { static int f = 0; static int gas_pattern = 0; static const int step = 60; /* Clear display buffer */ glUseProgram(pGeoId); glClearColor(0.2f, 0.4f, 0.7f, 1.0f); glClearDepthf(1.f); s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY0); s_RenderSystem.Clear(); glUseProgram(pGeoId); nn::math::Matrix44 proj; nn::math::MTX44Perspective(&proj, 65.0f, static_cast(nn::gx::DISPLAY0_WIDTH) / static_cast(nn::gx::DISPLAY0_HEIGHT), 1.0f, 200.f); nn::math::Matrix34 mv; nn::math::VEC3 camPos(0.f, 1.f, 16.0f); nn::math::VEC3 camUp(-1.f, 0.f, 0.f); nn::math::VEC3 target(0.f, 0.f, 0.f); nn::math::MTX34LookAt(&mv, &camPos, &camUp, &target); if (f == 0) SetGasColorTable(&gas,gasColorTable[gas_pattern]); /* Draw the Object */ glUseProgram(pGeoId); glUniformMatrix4fv(glGetUniformLocation(pGeoId, "uProjection"), 1, GL_TRUE, static_cast(proj)); nn::math::Matrix34 mv_rot, tmp; nn::math::MTX34RotXYZDeg(&tmp, 0.f, -90.f, 0.f); nn::math::MTX34Mult(&mv_rot, &mv, &tmp); nn::math::Vector3 scale(0.1f, 0.1f, 0.1f); nn::math::MTX34MultScale(&mv_rot, &mv_rot, &scale); nn::math::Vector3 trans(100.0f, 0.f, 0.f); nn::math::MTX34MultTranslate(&mv_rot, &mv_rot, &trans); nn::math::Matrix44 tmp_m(mv_rot); glUniformMatrix4fv(glGetUniformLocation(pGeoId, "uModelView"), 1, GL_TRUE, static_cast(tmp_m)); glBindTexture(GL_TEXTURE_COLLECTION_DMP, lutids[0]); nn::math::Vector4 lpos0(0.57735f, 0.57735f, 0.57735f, 0.f); glUniform4fv(glGetUniformLocation(pGeoId, "dmp_FragmentLightSource[0].position"), 1, static_cast(lpos0)); DrawObject(); /* Gas accumulation pass */ glUseProgram(pAccId); glDisable(GL_CULL_FACE); glFrontFace(GL_CCW); glCullFace(GL_BACK); glUniformMatrix4fv(glGetUniformLocation(pAccId, "uProjection"), 1, GL_TRUE, static_cast(proj)); nn::math::Matrix34 mv_tr; nn::math::Vector3 trans2(0.0f, -1.0f, static_cast(f - 20)); nn::math::MTX34MultTranslate(&mv_tr, &mv, &trans2); nn::math::Matrix44 tmp_mv_tr(mv_tr); glUniformMatrix4fv(glGetUniformLocation(pAccId, "uModelView"), 1, GL_TRUE, static_cast(tmp_mv_tr)); GasAccumulation(); s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY0); /* Gas shading pass */ GasShading(); /* swap buffer */ glFinish(); s_RenderSystem.SwapBuffers(); s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY1); s_RenderSystem.Clear(); s_RenderSystem.SwapBuffers(); s_RenderSystem.WaitVsync(NN_GX_DISPLAY_BOTH); if (++f == step) { gas_pattern = ++gas_pattern % 3; f = 0; } return !glGetError(); } /* ======================================================= */ /* main function */ /* ======================================================= */ void nnMain(void) { // Call only nn::applet::Enable to also allow execution from the HOME Menu // HOME Menu transitions, POWER Button presses, and sleep are all unsupported nn::applet::Enable(); // fs initialization nn::fs::Initialize(); const size_t ROMFS_BUFFER_SIZE = 1024 * 64; static char buffer[ROMFS_BUFFER_SIZE]; NN_UTIL_PANIC_IF_FAILED( nn::fs::MountRom(16, 16, buffer, ROMFS_BUFFER_SIZE)); /* Initialize the framebuffer and gas buffer*/ Initialize(); /* Initialize shaders */ if (ShaderInitialize() >= 0) { /*Initialize standard and gaseous objects */ SceneObjectInitialize(); while (1) { (void)DrawFrame(); } } GasFinalize(); UnloadObjects(); /* shutdown_display */ s_RenderSystem.Finalize(); s_AppHeap.Free(reinterpret_cast(s_HeapForMalloc)); s_AppHeap.Free(reinterpret_cast(s_HeapForGx)); s_AppHeap.Finalize(); }