/*---------------------------------------------------------------------------* Project: Horizon File: PartsysGas.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 "Util.h" #include "Loader.h" #include "Gas.h" #include #include "Memory.h" #include "demo.h" /* 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 plane; struct gas_data gas; /* 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; /*=======================================================*/ /* Sample specific. Different color variation for gas */ /*=======================================================*/ #define NUM_COLOR_SAMPLE 6 static float gasColorTable[NUM_COLOR_SAMPLE][24]= { { /* red flame */ 0.0f, 0.0f, 0.0f, 0.2f, 0.15f, 0.05f, 0.6f, 0.25f, 0.15f, 0.9f, 0.35f, 0.2f, 0.92f, 0.6f, 0.15f, 0.95f, 0.85f, 0.05f, 1.0f, 0.95f, 0.0f, 1.0f, 1.0f, 1.0f }, { /* blue flame */ 0.00f, 0.00f, 0.00f, 0.05f, 0.15f, 0.20f, 0.15f, 0.25f, 0.60f, 0.20f, 0.35f, 0.90f, 0.15f, 0.60f, 0.92f, 0.05f, 0.85f, 0.95f, 0.00f, 0.95f, 1.00f, 1.00f, 1.00f, 1.00f }, { /* Grey Gradient */ 0.000000f, 0.000000f, 0.000000f, 0.140000f, 0.140000f, 0.140000f, 0.280000f, 0.280000f, 0.280000f, 0.420000f, 0.420000f, 0.420000f, 0.560000f, 0.560000f, 0.560000f, 0.700000f, 0.700000f, 0.700000f, 0.840000f, 0.840000f, 0.840000f, 1.000000f, 1.000000f, 1.000000f }, { /* Pastel color */ 255.0f/255.0f, 191.0f/255.0f, 191.0f/255.0f, 255.0f/255.0f, 238.0f/255.0f, 191.0f/255.0f, 222.0f/255.0f, 255.0f/255.0f, 191.0f/255.0f, 191.0f/255.0f, 255.0f/255.0f, 207.0f/255.0f, 191.0f/255.0f, 254.0f/255.0f, 255.0f/255.0f, 191.0f/255.0f, 206.0f/255.0f, 255.0f/255.0f, 223.0f/255.0f, 191.0f/255.0f, 255.0f/255.0f, 255.0f/255.0f, 191.0f/255.0f, 238.0f/255.0f }, { /* Greenish */ 125.0f/255.0f, 255.0f/255.0f, 1.0f/255.0f, 173.0f/255.0f, 255.0f/255.0f, 35.0f/255.0f, 189.0f/255.0f, 255.0f/255.0f, 46.0f/255.0f, 204.0f/255.0f, 255.0f/255.0f, 57.0f/255.0f, 219.0f/255.0f, 255.0f/255.0f, 68.0f/255.0f, 229.0f/255.0f, 247.0f/255.0f, 65.0f/255.0f, 234.0f/255.0f, 230.0f/255.0f, 53.0f/255.0f, 239.0f/255.0f, 212.0f/255.0f, 40.0f/255.0f }, { /* Red strips */ 0.000000f, 0.000000f, 0.000000f, 1.000000f, 0.500000f, 0.000000f, 0.500000f, 0.000000f, 0.000000f, 1.000000f, 0.500000f, 0.000000f, 0.500000f, 0.000000f, 0.000000f, 1.000000f, 0.50000f, 0.000000f, 0.500000f, 0.000000f, 0.000000f, 1.000000f, 0.200000f, 0.300000f } }; /*=======================================================*/ /* Static function declaration */ /*=======================================================*/ static int DrawFrame(void); /*=======================================================*/ /* initialization */ /*=======================================================*/ static void Initialize(void) { /* Initialize display */ 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 */ GasInitialize(); } static void LoadParticleSystem1(struct _particleSys *pp) { GLfloat vertex[4] = {0.0f, 1.0f, 2.0f, 3.0f}; glGenBuffers(1, &pp->m_pSysPositionID) ; glBindBuffer(GL_ARRAY_BUFFER, pp->m_pSysPositionID); glBufferData(GL_ARRAY_BUFFER, 4 * sizeof(GLfloat), &vertex[0], GL_STATIC_DRAW); /*------------------------------------------------------------------------------------*/ /*--------Definition of the 4 control point positions---------------------------------*/ /*------------------------------------------------------------------------------------*/ /*-----------Control Point 1---------------------Control Point 2----------------------*/ pp->m_partsys_center.m[0][0] = 0.0f; /*|*/ pp->m_partsys_center.m[1][0] = -5.0f; pp->m_partsys_center.m[0][1] = -20.0f; /*|*/ pp->m_partsys_center.m[1][1] = -20.0f; pp->m_partsys_center.m[0][2] = 0.0f; /*|*/ pp->m_partsys_center.m[1][2] = 0.0f; pp->m_partsys_center.m[0][3] = 1.0f; /*|*/ pp->m_partsys_center.m[1][3] = 1.0f; /*-----------Control Point 3---------------------Control Point 4----------------------*/ pp->m_partsys_center.m[2][0] = 5.0f; /*|*/ pp->m_partsys_center.m[3][0] = 0.0f; pp->m_partsys_center.m[2][1] = 5.0f; /*|*/ pp->m_partsys_center.m[3][1] = 15.0f; pp->m_partsys_center.m[2][2] = 0.0f; /*|*/ pp->m_partsys_center.m[3][2] = 0.0f; pp->m_partsys_center.m[2][3] = 1.0f; /*|*/ pp->m_partsys_center.m[3][3] = 1.0f; /*------------------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------------*/ /*--------Definition of the 4 control point colors------------------------------------*/ /*------------------------------------------------------------------------------------*/ /*Color is not used in this sample. */ /*To modify the alpha value, please use pp->m_partsys_aspect[k][3] */ /*-----------Control Point 1---------------------Control Point 2----------------------*/ pp->m_partsys_color.m[0][0] = 0.0f; /*|*/ pp->m_partsys_color.m[1][0] = 1.0f; pp->m_partsys_color.m[0][1] = 0.0f; /*|*/ pp->m_partsys_color.m[1][1] = 0.0f; pp->m_partsys_color.m[0][2] = 0.0f; /*|*/ pp->m_partsys_color.m[1][2] = 0.0f; pp->m_partsys_color.m[0][3] = 1.0f; /*|*/ pp->m_partsys_color.m[1][3] = 1.0f; /*-----------Control Point 3---------------------Control Point 4----------------------*/ pp->m_partsys_color.m[2][0] = 0.0f; /*|*/ pp->m_partsys_color.m[3][0] = 0.0f; pp->m_partsys_color.m[2][1] = 1.0f; /*|*/ pp->m_partsys_color.m[3][1] = 0.0f; pp->m_partsys_color.m[2][2] = 0.0f; /*|*/ pp->m_partsys_color.m[3][2] = 1.0f; pp->m_partsys_color.m[2][3] = 0.5f; /*|*/ pp->m_partsys_color.m[3][3] = 0.0f; /*------------------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------------*/ /*--------Definition of the 4 bounding boxes------------------------------------------*/ /*--------Radii in X, Y and Z direction. W not used ----------------------------------*/ /*------------------------------------------------------------------------------------*/ /*-----------Control Point 1---------------------Control Point 2----------------------*/ pp->m_partsys_radius.m[0][0] = 0.0f; /*|*/ pp->m_partsys_radius.m[1][0] = 0.2f; pp->m_partsys_radius.m[0][1] = 0.0f; /*|*/ pp->m_partsys_radius.m[1][1] = 2.0f; pp->m_partsys_radius.m[0][2] = 0.0f; /*|*/ pp->m_partsys_radius.m[1][2] = 0.2f; pp->m_partsys_radius.m[0][3] = 1.0f; /*|*/ pp->m_partsys_radius.m[1][3] = 1.0f; /*-----------Control Point 3---------------------Control Point 4----------------------*/ pp->m_partsys_radius.m[2][0] = 1.0f; /*|*/ pp->m_partsys_radius.m[3][0] = 5.0f; pp->m_partsys_radius.m[2][1] = 10.0f; /*|*/ pp->m_partsys_radius.m[3][1] = 0.0f; pp->m_partsys_radius.m[2][2] = 1.0f; /*|*/ pp->m_partsys_radius.m[3][2] = 5.0f; pp->m_partsys_radius.m[2][3] = 1.0f; /*|*/ pp->m_partsys_radius.m[3][3] = 1.0f; /*------------------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------------*/ /*--------Definition of the particle aspect-------------------------------------------*/ /*--------Particle size, texture coordinates !!!??TBD ------------------------------*/ /*------------------------------------------------------------------------------------*/ /*Rotation disabled: Size, unused,unused,unused/alpha */ /*Rotation Enabled: Size, Angle, Radius, unused/alpha */ /*-----------Control Point 1---------------------Control Point 2----------------------*/ pp->m_partsys_aspect.m[0][0] = 0.0f; /*|*/ pp->m_partsys_aspect.m[1][0] = 4.0f; pp->m_partsys_aspect.m[0][1] = 0.0f; /*|*/ pp->m_partsys_aspect.m[1][1] = 0.0f; pp->m_partsys_aspect.m[0][2] = 0.9f; /*|*/ pp->m_partsys_aspect.m[1][2] = 0.9f; pp->m_partsys_aspect.m[0][3] = 1.0f; /*|*/ pp->m_partsys_aspect.m[1][3] = 1.0f; /*-----------Control Point 3---------------------Control Point 4----------------------*/ pp->m_partsys_aspect.m[2][0] = 6.0f; /*|*/ pp->m_partsys_aspect.m[3][0] = 30.0f; pp->m_partsys_aspect.m[2][1] = 0.0f; /*|*/ pp->m_partsys_aspect.m[3][1] = 0.0f; pp->m_partsys_aspect.m[2][2] = 0.9f; /*|*/ pp->m_partsys_aspect.m[3][2] = 0.9f; pp->m_partsys_aspect.m[2][3] = 0.0f; /*|*/ pp->m_partsys_aspect.m[3][3] = 0.0f; /*------------------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------------*/ pp->m_size_min_max[0] = 1.0f; pp->m_size_min_max[1] = static_cast(NN_GX_DISPLAY0_HEIGHT) / 2.0f; pp->m_random_seed[0] = 45.0f; pp->m_random_seed[1] = 2.564f + pp->m_random_seed[0]; pp->m_random_seed[2] = 1.15f + pp->m_random_seed[0]; pp->m_random_seed[3] = 0.9875f + pp->m_random_seed[0]; /* Core value for random Algorithm is based on pseudo-random number generators: X(n+1) = (a*Xn+b) mod m Expected values for uniform are [0] = a, [1] = b, [2] = m, [3] = 1/m */ pp->m_prng[0] = 17.0f; /* a */ pp->m_prng[1] = 37.0f; /* b */ pp->m_prng[2] = 65535.0f; /* m */ pp->m_prng[3] = 1.0f / (pp->m_prng[2]); /* 1/m */ pp->m_speed = 1.0f; /* emitter->particle_speed */ pp->m_particleCountMax = 60.0f; /* particle number */ /* Application only */ pp->simulationTime = 2.0f; pp->NFrame = 512; pp->dTime = pp->simulationTime / pp->NFrame; } static void SceneObjectInitialize(void) { /* Load object (non-gaseous object) */ loadDAT( "rom:/resources/planeXY3.dat", &plane); /* Load Gaseous object */ DefaultGasObject(&gas, gasColorTable[0]); /* Define the gaseous object geometry as a particle system */ LoadParticleSystem1(&gas.pSys); } static void UnloadObjects(void) { unloadDAT(&plane); return; } /*=======================================================*/ /* Initialization of 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); /* for normal geometry */ pGeoId = glCreateProgram(); glAttachShader(pGeoId, shaders[0]); glAttachShader(pGeoId, GL_DMP_FRAGMENT_SHADER_DMP); glBindAttribLocation(pGeoId, 0, "aPosition"); glLinkProgram(pGeoId); glValidateProgram(pGeoId); glUseProgram(pGeoId); /* for gas accumulation pass */ pAccId = glCreateProgram(); glAttachShader(pAccId, shaders[1]); glAttachShader(pAccId, shaders[3]); glAttachShader(pAccId, GL_DMP_FRAGMENT_SHADER_DMP); glBindAttribLocation(pAccId, 0, "attrCtrPointIndex"); glLinkProgram(pAccId); glValidateProgram(pAccId); glUseProgram(pAccId); /* for gas shading/pos synthesis pass */ 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); /* * Setup texture and blending unit * The color of the object is defined as a constant color from blending unit 0 */ glUniform1i(glGetUniformLocation(pGeoId, "dmp_Texture[0].samplerType"), GL_FALSE); glUniform1i(glGetUniformLocation(pGeoId, "dmp_TexEnv[0].combineRgb"), GL_REPLACE); glUniform1i(glGetUniformLocation(pGeoId, "dmp_TexEnv[0].combineAlpha"), GL_REPLACE); glUniform3i(glGetUniformLocation(pGeoId, "dmp_TexEnv[0].operandRgb"), GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_COLOR); glUniform3i(glGetUniformLocation(pGeoId, "dmp_TexEnv[0].operandAlpha"), GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA); glUniform3i(glGetUniformLocation(pGeoId, "dmp_TexEnv[0].srcRgb"), GL_CONSTANT, GL_CONSTANT, GL_CONSTANT); glUniform3i(glGetUniformLocation(pGeoId, "dmp_TexEnv[0].srcAlpha"), GL_CONSTANT, GL_CONSTANT, GL_CONSTANT); float almostblack[4] = {0.15f, 0.15f, 0.15f, 0.0f}; glUniform4fv(glGetUniformLocation(pGeoId, "dmp_TexEnv[0].constRgba"), 1, almostblack); /* * 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 */ glDisableVertexAttribArray(1); /* disable texture coordinate */ glDisableVertexAttribArray(2); /* disable color */ for (int i = 0; i < plane.obj_num; i++) { glBindBuffer(GL_ARRAY_BUFFER, plane.posVB); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)plane.obj[i].vtx_offset); for (unsigned j = plane.obj[i].patch_offset; j < plane.obj[i].patch_size + plane.obj[i].patch_offset; j++) { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, plane.idxVB); glDrawElements(GL_TRIANGLES, plane.patch[j].elm_size, GL_UNSIGNED_SHORT, (GLvoid*)(plane.patch[j].elm_offset + plane.obj[i].elm_offset)); } } /* * Finalization */ glDisableVertexAttribArray(0); } /*=======================================================*/ /* draw frame */ /*=======================================================*/ static int DrawFrame(void) { static int f = 0; static int pattern = 0; /* 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, m; nn::math::MTX44Perspective(&proj, 35.0f, static_cast(nn::gx::DISPLAY0_WIDTH) / static_cast(nn::gx::DISPLAY0_HEIGHT), 1.0f, 200.f); nn::math::Matrix34 mv; nn::math::Vector3 camPos(0.f, 0.f, 80.0f); nn::math::Vector3 camUp(0.f, 1.f, 0.f); nn::math::Vector3 target(0.f, 0.f, 0.f); nn::math::MTX34LookAt(&mv, &camPos, &camUp, &target); if (f == 0) { /* set next gas table */ SetGasColorTable(&gas,gasColorTable[pattern % NUM_COLOR_SAMPLE]); gas.pSys.simulationTime = 0.f; pattern++; } glUseProgram(pGeoId); glClearColor(0.2f, 0.4f, 0.7f, 1.0f); glClearDepthf(1.f); s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY0); s_RenderSystem.Clear(); { /* 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, 45.0f, 0.f); nn::math::MTX34Mult(&mv_rot, &mv, &tmp); nn::math::Vector3 scale(0.5f, 0.5f, 0.5f); nn::math::MTX34MultScale(&mv_rot, &mv_rot, &scale); m = nn::math::Matrix44(mv_rot); glUniformMatrix4fv(glGetUniformLocation(pGeoId, "uModelView"), 1, GL_TRUE, static_cast(m)); 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)); m = nn::math::Matrix44(mv); glUniformMatrix4fv(glGetUniformLocation(pAccId, "uModelView"), 1, GL_TRUE, static_cast(m)); GasAccumulation(); } s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY0); /* Gas shading pass */ GasShading(); gas.pSys.simulationTime += gas.pSys.dTime; /* 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 == gas.pSys.NFrame) f = 0; /* go to next gas pattern */ /* return 0 when 16 frames done */ 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(); /* Initialization of shaders */ if (ShaderInitialize() >= 0) { /*Initialize standard and gaseous objects */ SceneObjectInitialize(); /* Enter loop */ while (1) { DrawFrame(); } } UnloadObjects(); /* shutdown_display */ s_RenderSystem.Finalize(); s_AppHeap.Free(reinterpret_cast(s_HeapForMalloc)); s_AppHeap.Free(reinterpret_cast(s_HeapForGx)); s_AppHeap.Finalize(); }