/*---------------------------------------------------------------------------* Project: Horizon File: CommandBufferJump.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 #include "demo.h" #include "Util.h" #include "Loader.h" #include #include #include "Memory.h" #define APP_NAME "CommandBufferJump" #define STATE_SETTINGS 0 /* 0 - simple Blinn-Phong, 1 - generalized Blinn-Phong, 2 - Cook-Torrance */ static void State0(void); static void State1(void); static void State2(void); void (*render_state_func[])(void) = { State0, State1, State2, }; /* obj file loader class object */ dat_t robot; /* program id */ GLuint s_ProgramID; /* program ids */ GLuint s_ProgramIDs[3]; /* shader id */ GLuint s_ShaderID; /* texture id */ GLuint s_TextureID[3]; /* command list id */ GLuint s_CmdlistID[4]; #define NUM_OBJ 18 unsigned* s_SubrCommand[NUM_OBJ]; struct CmdlistInfo { GLvoid* bufferaddr; GLsizei buffersize; } s_CmdlistInfo[4]; /* 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 void State0(void) { GLfloat ls0[] = {1.f, 1.f, 0.f, 1.f}; GLfloat ms[] = {1.f, 1.f, 1.f, 1.f}; glUniform4fv(glGetUniformLocation(s_ProgramID, "dmp_FragmentLightSource[0].specular0"), 1, ls0); glUniform4fv(glGetUniformLocation(s_ProgramID, "dmp_FragmentMaterial.specular0"), 1, ms); /* to ignore 2nd specular term, set 0 to ms2. use of const reflection allows material specular2(ms2). */ GLfloat ms2[] = {0.f, 0.f, 0.f, 1.f}; glUniform4fv(glGetUniformLocation(s_ProgramID, "dmp_FragmentMaterial.specular1"), 1, ms2); glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutEnabledRefl"), GL_FALSE); glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutInputD0"), GL_LIGHT_ENV_NH_DMP); glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.absLutInputD0"), GL_TRUE); /* Because the 2nd specular term is not used, only the D0 table is used in configuration 0. */ glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.config"), GL_LIGHT_ENV_LAYER_CONFIG0_DMP); /* geometry factor is not considered. */ glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentLightSource[0].geomFactor1"), GL_FALSE); glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutEnabledD0"), GL_TRUE); glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.clampHighlights"), GL_FALSE); /* bind lookup table */ glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentMaterial.samplerD0"), 0); /* setup lookup table */ GLuint lutids[2]; glGenTextures(2, lutids); glBindTexture(GL_TEXTURE_COLLECTION_DMP, lutids[0]); GLfloat lut[512]; int j; memset(lut, 0, sizeof(lut)); for (j = 0; j < 256; j++) /* shininess is 10.0 */ lut[j] = powf((float)j/255.9375f, 10.f); /* shininess is 1.0 */ /* lut[j] = powf((float)j/255.9375f, 1.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(s_ProgramID, "dmp_TexEnv[0].combineRgb"), GL_REPLACE); glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].combineAlpha"), GL_REPLACE); glUniform3i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].operandRgb"), GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_COLOR); glUniform3i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].operandAlpha"), GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA); glUniform3i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].srcRgb"), GL_FRAGMENT_SECONDARY_COLOR_DMP, GL_CONSTANT, GL_CONSTANT); glUniform3i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].srcAlpha"), GL_CONSTANT, GL_CONSTANT, GL_CONSTANT); } /* Generalized Blinn-Phong reflection */ static void State1(void) { GLfloat ls0[] = {0.f, 1.f, 0.f, 1.f}; GLfloat ms[] = {1.f, 1.f, 1.f, 1.f}; glUniform4fv(glGetUniformLocation(s_ProgramID, "dmp_FragmentLightSource[0].specular0"), 1, ls0); glUniform4fv(glGetUniformLocation(s_ProgramID, "dmp_FragmentMaterial.specular0"), 1, ms); GLfloat ls20[] = {1.f, 0.01f, 0.25f, 1.f}; glUniform4fv(glGetUniformLocation(s_ProgramID, "dmp_FragmentLightSource[0].specular1"), 1, ls20); /* use of const reflection allows material specular2(ms2). */ glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutEnabledRefl"), GL_FALSE); glUniform4fv(glGetUniformLocation(s_ProgramID, "dmp_FragmentMaterial.specular1"), 1, ms); glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutInputD1"), GL_LIGHT_ENV_NH_DMP); glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutInputD0"), GL_LIGHT_ENV_NH_DMP); glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.absLutInputD1"), GL_TRUE); glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.absLutInputD0"), GL_TRUE); glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.config"), GL_LIGHT_ENV_LAYER_CONFIG2_DMP); glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentLightSource[0].geomFactor0"), GL_FALSE); glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentLightSource[0].geomFactor1"), GL_FALSE); glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutEnabledD0"), GL_TRUE); glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutEnabledD1"), GL_TRUE); glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.clampHighlights"), GL_FALSE); /* bind lookup table */ glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentMaterial.samplerD1"), 0); glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentMaterial.samplerD0"), 1); /* setup lookup table */ GLuint lutids[3]; glGenTextures(3, lutids); glBindTexture(GL_TEXTURE_COLLECTION_DMP, lutids[0]); GLfloat lut[512]; int j; memset(lut, 0, sizeof(lut)); /* set layer1 distribution function */ for (j = 0; j < 256; j++) /* when s is equal to 2.0/m^2, highlight specular is similar between power function and gaussian function. when s is 90.0, m is 0.149, and when s is 2.0, m is 1.0. */ /* lut[j] = powf((float)j/255.9375f, 90.f); */ lut[j] = gaussian((float)j/255.9375f, 0.149f); 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); /* set layer2 distribution function */ memset(lut, 0, sizeof(lut)); for (j = 0; j < 256; j++) /* lut[j] = powf((float)j/255.9375f, 2.f); */ lut[j] = gaussian((float)j/255.9375f, 1.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_TEXTURE1_DMP, lutids[2]); glTexImage1D(GL_LUT_TEXTURE1_DMP, 0, GL_LUMINANCEF_DMP, 512, 0, GL_LUMINANCEF_DMP, GL_FLOAT, lut); glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].combineRgb"), GL_REPLACE); glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].combineAlpha"), GL_REPLACE); glUniform3i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].operandRgb"), GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_COLOR); glUniform3i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].operandAlpha"), GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA); glUniform3i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].srcRgb"), GL_FRAGMENT_SECONDARY_COLOR_DMP, GL_CONSTANT, GL_CONSTANT); glUniform3i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].srcAlpha"), GL_CONSTANT, GL_CONSTANT, GL_CONSTANT); } /* Full-scope Cook-Torrance reflection */ static void State2(void) { GLfloat ls0[] = {1.f, 1.f, 1.f, 1.f}; GLfloat disable[] = {0.f, 0.f, 0.f, 0.f}; /* to ignore specular 1st term, set 0. */ glUniform4fv(glGetUniformLocation(s_ProgramID, "dmp_FragmentMaterial.specular0"), 1, disable); glUniform4fv(glGetUniformLocation(s_ProgramID, "dmp_FragmentLightSource[0].specular1"), 1, ls0); /* to use Rr, Rg, Rb table */ glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutEnabledRefl"), GL_TRUE); glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutInputRR"), GL_LIGHT_ENV_VH_DMP); glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutInputRG"), GL_LIGHT_ENV_VH_DMP); glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutInputRB"), GL_LIGHT_ENV_VH_DMP); glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutInputD0"), GL_LIGHT_ENV_NH_DMP); glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutInputD1"), GL_LIGHT_ENV_NH_DMP); glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.absLutInputRR"), GL_FALSE); glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.absLutInputRG"), GL_FALSE); glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.absLutInputRB"), GL_FALSE); glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.absLutInputD0"), GL_FALSE); glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.absLutInputD1"), GL_FALSE); /* below we make bit shift after sampling table of Fresnel reflection we have to do this because we do not have HDR(sky has high intensity) */ glUniform1f(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutScaleRR"), 2.f); glUniform1f(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutScaleRG"), 2.f); glUniform1f(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutScaleRB"), 2.f); glUniform1f(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutScaleD0"), 2.f); glUniform1f(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutScaleD1"), 2.f); glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.config"), GL_LIGHT_ENV_LAYER_CONFIG4_DMP); glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutEnabledD0"), GL_TRUE); glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.lutEnabledD1"), GL_TRUE); glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_LightEnv.clampHighlights"), GL_FALSE); /* geometory factor is considered in Cook-Torrance model */ glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentLightSource[0].geomFactor0"), GL_TRUE); glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentLightSource[0].geomFactor1"), GL_TRUE); /* bind lookup table */ glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentMaterial.samplerRR"), 0); glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentMaterial.samplerRG"), 1); glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentMaterial.samplerRB"), 2); glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentMaterial.samplerD1"), 3); glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentMaterial.samplerD0"), 4); /* setup lookup table */ GLuint lutids[6]; glGenTextures(6, lutids); glBindTexture(GL_TEXTURE_COLLECTION_DMP, lutids[0]); GLfloat lut[512]; int j; memset(lut, 0, sizeof(lut)); glBindTexture(GL_LUT_TEXTURE4_DMP, lutids[5]); glTexImage1D(GL_LUT_TEXTURE4_DMP, 0, GL_LUMINANCEF_DMP, 512, 0, GL_LUMINANCEF_DMP, GL_FLOAT, lut); /* in this sample, gold is used as fresnel factor, and real and imaginary part of refractive index of gold is following. n k --------------------------------- 0.183521, 2.959155 at 630 nm 0.516924, 2.276178 at 525 nm 1.464924, 1.860113 at 455 nm */ /* setup Rr table */ for (j = 0; j < 128; j++) lut[j] = nk_fresnel((float)j/128.f, 0.183521f, 2.959155f); for (j = 0; j < 127; j++) lut[j + 256] = lut[j+1] - lut[j]; lut[127 + 256] = nk_fresnel(1.f, 0.183521f, 2.959155f) - lut[127]; glBindTexture(GL_LUT_TEXTURE0_DMP, lutids[1]); glTexImage1D(GL_LUT_TEXTURE0_DMP, 0, GL_LUMINANCEF_DMP, 512, 0, GL_LUMINANCEF_DMP, GL_FLOAT, lut); /* setup Rg table */ memset(lut, 0, sizeof(lut)); for (j = 0; j < 128; j++) lut[j] = nk_fresnel((float)j/128.f, 0.516924f, 2.276178f); for (j = 0; j < 127; j++) lut[j + 256] = lut[j+1] - lut[j]; lut[127 + 256] = nk_fresnel(1.f, 0.516924f, 2.276178f) - lut[127]; glBindTexture(GL_LUT_TEXTURE1_DMP, lutids[2]); glTexImage1D(GL_LUT_TEXTURE1_DMP, 0, GL_LUMINANCEF_DMP, 512, 0, GL_LUMINANCEF_DMP, GL_FLOAT, lut); /* setup Rb table */ memset(lut, 0, sizeof(lut)); for (j = 0; j < 128; j++) lut[j] = nk_fresnel((float)j/128.f, 1.464924f, 1.860113f); for (j = 0; j < 127; j++) lut[j + 256] = lut[j+1] - lut[j]; lut[127 + 256] = nk_fresnel(1.f, 1.464924f, 1.860113f) - lut[127]; glBindTexture(GL_LUT_TEXTURE2_DMP, lutids[3]); glTexImage1D(GL_LUT_TEXTURE2_DMP, 0, GL_LUMINANCEF_DMP, 512, 0, GL_LUMINANCEF_DMP, GL_FLOAT, lut); /* don't use D0 table, so setup D1 table only */ memset(lut, 0, sizeof(lut)); /* Beckmann function is used in m=1.0 and m=0.5 */ for (j = 1; j < 128; j++) lut[j] = beckmann((float)j/128.f, 1.f); /* m=1.0 */ /* lut[j] = beckmann((float)j/128.f, 0.5f); */ /* m=0.5 */ for (j = 0; j < 127; j++) lut[j + 256] = lut[j+1] - lut[j]; lut[127 + 256] = 1.f - lut[127]; glBindTexture(GL_LUT_TEXTURE3_DMP, lutids[4]); glTexImage1D(GL_LUT_TEXTURE3_DMP, 0, GL_LUMINANCEF_DMP, 512, 0, GL_LUMINANCEF_DMP, GL_FLOAT, lut); glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].combineRgb"), GL_REPLACE); glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].combineAlpha"), GL_REPLACE); glUniform3i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].operandRgb"), GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_COLOR); glUniform3i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].operandAlpha"), GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA); glUniform3i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].srcRgb"), GL_FRAGMENT_SECONDARY_COLOR_DMP, GL_CONSTANT, GL_CONSTANT); glUniform3i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].srcAlpha"), GL_CONSTANT, GL_CONSTANT, GL_CONSTANT); } /* generate simple object */ static void LoadObjects(void) { /* load obj file geometry and diffuse texture */ loadDAT( "rom:/resources/robot1.dat", &robot); } static void UnloadObjects(void) { unloadDAT(&robot); return; } static void CreateCommand() { nn::math::Matrix44 proj; nn::math::Matrix34 mv, rot; // Different material setting commands each configured by State0(), State1(), and State2() are stored in s_CmdlistID[0], s_CmdlistID[1], and s_CmdlistID[2], respectively. // // // A command for drawing is stored at the front in s_CmdlistID[3]. // GLuint currentCmdlist; nngxGetCmdlistParameteri(NN_GX_CMDLIST_BINDING, (GLint*)¤tCmdlist); for (int prog = 0; prog < 3; prog++) { s_ProgramID = s_ProgramIDs[prog]; nngxBindCmdlist(s_CmdlistID[prog]); glUseProgram(s_ProgramID); glBindTexture(GL_TEXTURE_COLLECTION_DMP, s_TextureID[prog]); /* setup projection matrix */ nn::math::MTX44Frustum(&proj, -0.06f, 0.06f, -0.06f * nn::gx::DISPLAY0_HEIGHT / nn::gx::DISPLAY0_WIDTH, 0.06f * nn::gx::DISPLAY0_HEIGHT / nn::gx::DISPLAY0_WIDTH, 0.2f, 200.f); glUniformMatrix4fv(glGetUniformLocation(s_ProgramID, "uProjection"), 1, GL_TRUE, static_cast(proj)); nn::math::Vector3 camPos(0.f, 0.f, 6.f); nn::math::Vector3 camUp(0.f, 1.f, 0.f); nn::math::Vector3 target(0.f, 0.f, 0.f); nn::math::MTX34RotXYZDeg(&rot, 0.f, 0.f, -90.0f); nn::math::MTX34LookAt(&mv, &camPos, &camUp, &target); nn::math::MTX34Mult(&mv, &rot, &mv); /* setup light direction */ nn::math::Vector4 lpos0(0.f, 1.f, 1.f, 0.f); nn::math::Vector4 mv0(mv.m[0][0], mv.m[0][1], mv.m[0][2], mv.m[0][3]); nn::math::Vector4 mv1(mv.m[1][0], mv.m[1][1], mv.m[1][2], mv.m[1][3]); nn::math::Vector4 mv2(mv.m[2][0], mv.m[2][1], mv.m[2][2], mv.m[2][3]); nn::math::Vector4 lpos(nn::math::VEC4Dot(&mv0, &lpos0), nn::math::VEC4Dot(&mv1, &lpos0), nn::math::VEC4Dot(&mv2, &lpos0), lpos0.w); glUniform4fv(glGetUniformLocation(s_ProgramID, "dmp_FragmentLightSource[0].position"), 1, static_cast(lpos)); // Create a material setting comment nngxUpdateState(NN_GX_STATE_ALL); nngxValidateState(NN_GX_STATE_ALL, GL_TRUE); // Add a Channel 1 kick command // Pad with dummy commands as necessary unsigned retCmd[2] = {0x00000001, 0x000f023d}; unsigned emptyCmd[2] = {0x00000000, 0x00000200}; GLsizei buffersize; nngxGetCmdlistParameteri(NN_GX_CMDLIST_USED_BUFSIZE, (GLint*)&buffersize); if ((buffersize & 8) == 0) nngxAdd3DCommand(emptyCmd, sizeof(emptyCmd), GL_TRUE); nngxAdd3DCommand(retCmd, sizeof(retCmd), GL_TRUE); // Save the sub-routine used for setting materials in s_CmdlistInfo[0-2]. nngxGetCmdlistParameteri(NN_GX_CMDLIST_USED_BUFSIZE, (GLint*)&s_CmdlistInfo[prog].buffersize); nngxGetCmdlistParameteri(NN_GX_CMDLIST_TOP_BUFADDR, (GLint*)&s_CmdlistInfo[prog].bufferaddr); nngxUpdateBuffer(s_CmdlistInfo[prog].bufferaddr, s_CmdlistInfo[prog].buffersize); glEnableVertexAttribArray(0); glEnableVertexAttribArray(1); if (prog == 0) { // Create a command for drawing in s_CmdlistID[3]. nngxBindCmdlist(s_CmdlistID[3]); /* draw objects */ for (int i = 0; i < robot.obj_num; i++) { glBindBuffer(GL_ARRAY_BUFFER, robot.posVB); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)robot.obj[i].vtx_offset); glBindBuffer(GL_ARRAY_BUFFER, robot.normVB); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void*)robot.obj[i].nrm_offset); for (unsigned j = robot.obj[i].patch_offset; j < robot.obj[i].patch_size + robot.obj[i].patch_offset; j++) { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, robot.idxVB); glDrawElements(GL_TRIANGLES, robot.patch[j].elm_size, GL_UNSIGNED_SHORT, (GLvoid*)(robot.patch[j].elm_offset + robot.obj[i].elm_offset)); } } // Add a Channel 1 kick command // Pad with dummy commands as necessary nngxGetCmdlistParameteri(NN_GX_CMDLIST_USED_BUFSIZE, (GLint*)&buffersize); if ((buffersize & 8) == 0) nngxAdd3DCommand(emptyCmd, sizeof(emptyCmd), GL_TRUE); nngxAdd3DCommand(retCmd, sizeof(retCmd), GL_TRUE); // Save a sub-routine for the drawing command in s_CmdlistInfo[3]. nngxGetCmdlistParameteri(NN_GX_CMDLIST_USED_BUFSIZE, (GLint*)&s_CmdlistInfo[3].buffersize); nngxGetCmdlistParameteri(NN_GX_CMDLIST_TOP_BUFADDR, (GLint*)&s_CmdlistInfo[3].bufferaddr); nngxUpdateBuffer(s_CmdlistInfo[3].bufferaddr, s_CmdlistInfo[3].buffersize); } } nngxBindCmdlist(currentCmdlist); } int DrawFrame(void) { static int f = 0; nn::math::Matrix44 proj; nn::math::Matrix34 mv, rot, trans, scale; s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY0); s_RenderSystem.Clear(); if (f == 0) CreateCommand(); int num_obj = (f / 60) % NUM_OBJ + 1; // Draw the number of models given by num_obj. for (int obj = 0; obj < num_obj; obj++) { unsigned* modelViewCommand = s_SubrCommand[obj]; // Create model view command nn::math::Vector3 camPos(0.f, 0.f, 6.f); nn::math::Vector3 camUp(0.f, 1.f, 0.f); nn::math::Vector3 target(0.f, 0.f, 0.f); nn::math::MTX34RotXYZDeg(&rot, 0.f, 0.f, -90.0f); nn::math::MTX34LookAt(&mv, &camPos, &camUp, &target); nn::math::MTX34Mult(&mv, &rot, &mv); nn::math::MTX34RotXYZDeg(&rot, 0.f, static_cast((float)(360.f / NUM_OBJ * obj) - f), 0.f); nn::math::MTX34Mult(&mv, &mv, &rot); nn::math::Vector3 Trans(2.0f, 0.f, 0.f); nn::math::MTX34Translate(&trans, &Trans); nn::math::MTX34Mult(&mv, &mv, &trans); nn::math::Vector3 Scale(0.25f, 0.25f, 0.25f); nn::math::MTX34Scale(&scale, &Scale); nn::math::MTX34Mult(&mv, &mv, &scale); nn::math::Matrix44 m(mv); // Create a sub-routine for configuring the model view int index = 0; modelViewCommand[index++] = 0x80000004; modelViewCommand[index++] = 0x000f02c0; for (int i = 0; i < 4; i++) for (int j = 0; j < 4; j++) { float v = m.m[i][3 - j]; modelViewCommand[index++] = *(unsigned*)&v; if (i == 0 && j == 0) modelViewCommand[index++] = 0x00ff02c1; } modelViewCommand[index++] = 0x00000000; // Pad the last four bytes of the burst. if ((index & 2) == 0) { // Padding for 16-byte alignment modelViewCommand[index++] = 0x00000000; modelViewCommand[index++] = 0x00000200; } // Channel 1 kick command modelViewCommand[index++] = 0x00000001; modelViewCommand[index++] = 0x000f023d; // Clear the cache nngxUpdateBuffer(modelViewCommand, sizeof(unsigned) * index); // Apply the sub-routine for configuring materials nngxAddSubroutineCommand(s_CmdlistInfo[obj % 3].bufferaddr, s_CmdlistInfo[obj % 3].buffersize); // Apply the sub-routine for configuring the model view nngxAddSubroutineCommand(modelViewCommand, sizeof(unsigned) * index); // Apply the sub-routine for the draw command nngxAddSubroutineCommand(s_CmdlistInfo[3].bufferaddr, s_CmdlistInfo[3].buffersize); } s_RenderSystem.SwapBuffers(); s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY1); s_RenderSystem.Clear(); s_RenderSystem.SwapBuffers(); s_RenderSystem.WaitVsync(NN_GX_DISPLAY_BOTH); f++; return !glGetError(); } /* initialization */ static int 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_GxHeapSize); for (int i = 0; i < 3; i++) s_ProgramIDs[i] = glCreateProgram(); s_ShaderID = 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(1, &s_ShaderID, GL_PLATFORM_BINARY_DMP, buf, read); file.Finalize(); s_AppHeap.Free(buf); GLuint currentCmdlist; nngxGetCmdlistParameteri(NN_GX_CMDLIST_BINDING, (GLint*)¤tCmdlist); for (int i = 0; i < 3; i++) { s_ProgramID = s_ProgramIDs[i]; nngxGenCmdlists(1, &s_CmdlistID[i]); nngxBindCmdlist(s_CmdlistID[i]); nngxCmdlistStorage(0x8000, 16); glAttachShader(s_ProgramID, s_ShaderID); glAttachShader(s_ProgramID, GL_DMP_FRAGMENT_SHADER_DMP); glBindAttribLocation(s_ProgramID, 0, "aPosition"); glBindAttribLocation(s_ProgramID, 1, "aNormal"); glLinkProgram(s_ProgramID); glValidateProgram(s_ProgramID); glUseProgram(s_ProgramID); } nngxGenCmdlists(1, &s_CmdlistID[3]); nngxBindCmdlist(s_CmdlistID[3]); nngxCmdlistStorage(0x10000, 16); GLint SubrCommandStart; nngxGetCmdlistParameteri(NN_GX_CMDLIST_TOP_BUFADDR, (GLint*)&SubrCommandStart); // s_SubrCommand stores a subroutine for configuring the model view for each object. for (int i = 0; i < NUM_OBJ; i++) s_SubrCommand[i] = (unsigned*)(SubrCommandStart + 0x2000 + 0x100 * i); nngxBindCmdlist(currentCmdlist); glClearColor(0.36f, 0.42f, 0.5f, 1.0f); glClearDepthf(1.f); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LESS); glEnable(GL_CULL_FACE); glFrontFace(GL_CCW); glCullFace(GL_BACK); LoadObjects(); /* set another render state */ for (int i = 0; i < 3; i++) { s_ProgramID = s_ProgramIDs[i]; glUseProgram(s_ProgramID); (*render_state_func[i])(); /* enable DMP fragment lighting */ glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentLighting.enabled"), GL_TRUE); glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentLightSource[0].enabled"), GL_TRUE); glGetIntegerv(GL_TEXTURE_COLLECTION_BINDING_DMP, (GLint*)&s_TextureID[i]); } return 0; } void nnMain(void) { // Call only the nn::applet::Enable function 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)); /* initialization */ if (Initialize() >= 0) { /* 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(); }