/* *------------------------------------------------------------ * 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 "Memory.h" #include "demo.h" /* program id */ GLuint pAccId; GLuint pPostId; /* shader id */ GLuint s_Shaders[2]; /* Standard object (triangles, not gaseous object) */ struct gas_data gas; dat_t plane; /* 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 */ GasInitialize(); } static void SceneObjectInitialize(void) { /* Load object (non-gaseous object) */ loadDAT( "rom:/resources/planeXY3.dat", &plane); /* Load Gaseous object */ float tr_flame[24] = { 0.0f, 0.00f, 0.0f, /* 0 */ 0.2f, 0.15f, 0.05f, /* 1 */ 0.6f, 0.25f, 0.15f, /* 2 */ 0.9f, 0.35f, 0.2f, /* 3 */ 0.92f, 0.6f, 0.15f, /* 4 */ 0.95f, 0.85f, 0.05f, /* 5 */ 1.0f, 0.95f, 0.0f, /* 6 */ 1.0f, 1.0f, 1.0f /* 7 */ }; DefaultGasObject(&gas, tr_flame); /* Define the gaseous object geometry */ /* A simple quad in this sample */ float cx = 0.0; float cy = 0.0; float rd = 8.0; float _vertex[16]= { cx - rd, cy - rd, 0.0f, 1.0f, cx - rd, cy + rd, 0.0f, 1.0f, cx + rd, cy + rd, 0.0f, 1.0f, cx + rd, cy - rd, 0.0f, 1.0f }; float density = 1.0; float _color[4]= {density, density, density, density }; float t0 = 0.0f, t1 = 1.0f; float _texture[8]= { t0, t0, t1, t0, t1, t1, t0, t1 }; glGenBuffers(1, &gas.gasgeo_center_ID); glGenBuffers(1, &gas.gasgeo_density_ID); glGenBuffers(1, &gas.gasgeo_tx0_ID); glGenBuffers(1, &gas.gasgeo_tri_ID); glBindBuffer(GL_ARRAY_BUFFER, gas.gasgeo_center_ID); glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 16, &_vertex[0], GL_STATIC_DRAW); gas.gasgeo_size = 6; glBindBuffer(GL_ARRAY_BUFFER, gas.gasgeo_tx0_ID); glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 8, &_texture[0], GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, gas.gasgeo_density_ID); glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 4, &_color[0], GL_STATIC_DRAW); GLushort idxs[6] = {0, 1, 2, 0, 2, 3}; glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gas.gasgeo_tri_ID); glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6*sizeof(GLushort), idxs, GL_STATIC_DRAW); } /*=======================================================*/ /* finalization */ /*=======================================================*/ static void UnloadObjects(void) { unloadDAT(&plane); return; } /*=======================================================*/ /* Initialization of s_Shaders */ /*=======================================================*/ int ShaderInitialize(void) { s_Shaders[0] = glCreateShader(GL_VERTEX_SHADER); s_Shaders[1] = glCreateShader(GL_VERTEX_SHADER); 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(2, s_Shaders, GL_PLATFORM_BINARY_DMP, buf, read); file.Finalize(); s_AppHeap.Free(buf); pAccId = glCreateProgram(); glAttachShader(pAccId, s_Shaders[0]); glAttachShader(pAccId, GL_DMP_FRAGMENT_SHADER_DMP); glBindAttribLocation(pAccId, 0, "aPosition"); glBindAttribLocation(pAccId, 1, "aTexCoord"); glBindAttribLocation(pAccId, 2, "aColor"); glLinkProgram(pAccId); glValidateProgram(pAccId); glUseProgram(pAccId); pPostId = glCreateProgram(); glAttachShader(pPostId, s_Shaders[1]); 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(pAccId); glClearColor(0.2f, 0.4f, 0.7f, 1.0f); glClearDepthf(1.f); /* Set fragment operation mode to GL_FRAGOP_MODE_GL_DMP */ glUniform1i(glGetUniformLocation(pAccId, "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(pAccId, "dmp_Texture[0].samplerType"), GL_FALSE); glUniform1i(glGetUniformLocation(pAccId, "dmp_TexEnv[0].combineRgb"), GL_REPLACE); glUniform1i(glGetUniformLocation(pAccId, "dmp_TexEnv[0].combineAlpha"), GL_REPLACE); glUniform3i(glGetUniformLocation(pAccId, "dmp_TexEnv[0].operandRgb"), GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_COLOR); glUniform3i(glGetUniformLocation(pAccId, "dmp_TexEnv[0].operandAlpha"), GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA); glUniform3i(glGetUniformLocation(pAccId, "dmp_TexEnv[0].srcRgb"), GL_CONSTANT, GL_PRIMARY_COLOR, GL_PRIMARY_COLOR); glUniform3i(glGetUniformLocation(pAccId, "dmp_TexEnv[0].srcAlpha"), GL_CONSTANT, GL_PRIMARY_COLOR, GL_PRIMARY_COLOR); float almostblack[4] = {0.15f, 0.15f, 0.15f, 0.0f}; glUniform4fv(glGetUniformLocation(pAccId, "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 const int step = 60; /* Clear display buffer */ glBindFramebuffer(GL_FRAMEBUFFER, DISPLAY_BUFFER); glClearColor(0.2f, 0.4f, 0.7f, 1.0f); glClearDepthf(1.f); s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY0); s_RenderSystem.Clear(); glUseProgram(pAccId); nn::math::Matrix44 proj, m; nn::math::MTX44Perspective(&proj, 45.0f, static_cast(DISPLAY_WIDTH) / static_cast(DISPLAY_HEIGHT), 1.0f, 200.f); glUniformMatrix4fv(glGetUniformLocation(pAccId, "uProjection"), 1, GL_TRUE, static_cast(proj)); nn::math::Matrix34 mv, rot; 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); nn::math::MTX34RotXYZDeg(&rot, 0.f, 0.f, -90.0f); nn::math::MTX34Mult(&mv, &mv, &rot); { /* Draw the Object */ nn::math::Matrix34 mv_rot; nn::math::MTX34RotXYZDeg(&mv_rot, 0.f, 45.0f, 0.f); nn::math::MTX34Mult(&mv_rot, &mv, &mv_rot); m = nn::math::Matrix44(mv_rot); glUniformMatrix4fv(glGetUniformLocation(pAccId, "uModelView"), 1, GL_TRUE, static_cast(m)); DrawObject(); } /* Draw Z buffer for accumulation */ GasRenderAccumulationZBuffer(DrawObject); { /* Gas accumulation pass */ nn::math::Matrix34 mv_tr; nn::math::Vector3 trans(static_cast(f - 20), 0.f, 0.f); nn::math::MTX34MultTranslate(&mv_tr, &mv, &trans); m = nn::math::Matrix44(mv_tr); glUniformMatrix4fv(glGetUniformLocation(pAccId, "uModelView"), 1, GL_TRUE, static_cast(m)); GasAccumulation(); } /* Gas shading pass */ GasShading(); /* Blend shading result to color buffer */ s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY0); GasBlendShadingResult(); /* 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) 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(); /* Initialization of s_Shaders */ if (ShaderInitialize() >= 0) { /*Initialize standard and gaseous objects */ SceneObjectInitialize(); /* Enter loop */ while (1) { (void)DrawFrame(); } } UnloadObjects(); /* shutdown_display */ s_RenderSystem.Finalize(); s_AppHeap.Free(reinterpret_cast(s_HeapForMalloc)); s_AppHeap.Free(reinterpret_cast(s_HeapForGx)); s_AppHeap.Finalize(); }