/*---------------------------------------------------------------------------* Project: Horizon File: GasColorSimple.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 "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 */ GLuint depthStencilBufferId = s_RenderSystem.GetRenderBufferObjectId(NN_GX_DISPLAY0, GL_DEPTH_STENCIL_ATTACHMENT); GasInitialize(depthStencilBufferId); } 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(); } { /* 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 */ s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY0); 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) f = 0; /* 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 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(); }