/*---------------------------------------------------------------------------* Project: Horizon File: LightingMicrofacet.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 "Memory.h" #define APP_NAME "LightingMicrofacet" #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; /* shader id */ GLuint s_ShaderID; /* 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 geometory and diffuse texture */ loadDAT( "rom:/resources/robot1.dat", &robot); } static void UnloadObjects(void) { unloadDAT(&robot); return; } int DrawFrame(void) { static int f = 0; nn::math::Matrix44 proj; nn::math::Matrix34 mv, rot; s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY0); s_RenderSystem.Clear(); /* 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)); /* setup modelview matrix */ nn::math::MTX34RotXYZDeg(&rot, 0.f, static_cast(-f), 0.f); nn::math::MTX34Mult(&mv, &mv, &rot); nn::math::Matrix44 m(mv); glUniformMatrix4fv(glGetUniformLocation(s_ProgramID, "uModelView"), 1, GL_TRUE, static_cast(m)); glEnableVertexAttribArray(0); glEnableVertexAttribArray(1); /* 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)); } } glFinish(); 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); s_ProgramID = 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); 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); 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 */ (*render_state_func[STATE_SETTINGS])(); /* enable DMP fragment lighting */ glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentLighting.enabled"), GL_TRUE); glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentLightSource[0].enabled"), GL_TRUE); return 0; } 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)); /* 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(); }