/*---------------------------------------------------------------------------* Project: Horizon File: gx_FragmentLightingSimple.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 $ *---------------------------------------------------------------------------*/ #include #include #include #include #include #include #include #include "demo.h" namespace { GLuint s_ProgramId = 0; GLuint s_ShaderId = 0; nn::fnd::ExpHeap s_AppHeap; uptr s_AddrForGxHeap; const u32 s_GxHeapSize = 0x400000; demo::RenderSystem s_RenderSystem; nn::math::Vector3 s_CameraPosition(0.0f, 4.0f, 6.0f); nn::math::Vector3 s_CameraUp(0.0f, 1.0f, 0.0f); nn::math::Vector3 s_CameraTarget(0.0f, 0.0f, 0.0f); nn::math::Matrix34 s_ViewMatrix; nn::math::Matrix44 s_Display0ProjectionMatrix; nn::math::Matrix44 s_Display1ProjectionMatrix; const u32 MAX_LIGHT_NUM = 4; f32 s_GlobalAmbientLight[] = { 0.4f, 0.4f, 0.4f, 1.0f}; demo::Light s_LightArray[MAX_LIGHT_NUM]; f32 s_LightPhi[MAX_LIGHT_NUM]; f32 s_LightRadius = 3.0f; f32 s_LightDeltaPhi = 1.0f; f32 s_MaterialAmbient[] = {0.2f, 0.2f, 0.2f, 1.0f}; f32 s_MaterialDiffuse[] = {0.6f, 0.6f, 0.6f, 1.0f}; f32 s_MaterialSpecular0[] = {1.0f, 1.0f, 1.0f, 1.0f}; f32 s_MaterialSpecular1[] = {0.0f, 0.0f, 0.0f, 1.0f}; u32 s_MaterialShininess = 8; demo::Cube s_Cube; const u32 MAX_SPHERE_NUM = MAX_LIGHT_NUM; demo::Sphere s_LightSphereArray[MAX_SPHERE_NUM]; GLuint s_D0LutTextureId = 0; } void InitializeGraphics(void); void InitializeLights(void); void InitializeShader(void); void InitializeD0Lut(const u32& materialShininess); void UseShader(void); void UpdateCamera(void); void UpdateLights(void); void DrawDisplay0(void); void DrawDisplay1(void); void UseShader(void); void UpdateBody(demo::Body& body); void DrawBody(demo::Body& body); void SetLightUniform(void); void DrawLights(void); void Initialize(void) { // 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)); InitializeGraphics(); } void InitializeGraphics(void) { s_AppHeap.Initialize(nn::os::GetDeviceMemoryAddress(), nn::os::GetDeviceMemorySize() ); s_AddrForGxHeap = reinterpret_cast(s_AppHeap.Allocate(s_GxHeapSize)); s_RenderSystem.Initialize(s_AddrForGxHeap, s_GxHeapSize); glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClearDepthf(1.0f); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LESS); glEnable(GL_CULL_FACE); glFrontFace(GL_CCW); glCullFace(GL_BACK); InitializeLights(); InitializeShader(); // Initialize projection matrix nn::math::MTX44PerspectivePivotDeg(&s_Display0ProjectionMatrix, 45.0f, demo::DISPLAY0_ASPECT, 0.1f, 20.0f, nn::math::PIVOT_UPSIDE_TO_TOP); nn::math::MTX44PerspectivePivotDeg(&s_Display1ProjectionMatrix, 45.0f, demo::DISPLAY1_ASPECT, 0.1f, 20.0f, nn::math::PIVOT_UPSIDE_TO_TOP); // Initialize cube u32 vertexAttributes = demo::VERTEX_POSITION_ATTRIBUTE | demo::VERTEX_COLOR_ATTRIBUTE | demo::VERTEX_NORMAL_ATTRIBUTE; s_Cube.InitializeCube(vertexAttributes, 1.5f, 1.5f, 1.5f); s_Cube.SetColor(1.0f, 0.0f, 0.0f); s_Cube.SetWorldPosition(0.0f, 0.0f, 0.0f); s_Cube.SetWorldAngle(0.0f, 0.0f, 0.0f); // Initialize sphere for (u32 sphereIndex = 0; sphereIndex < MAX_SPHERE_NUM; sphereIndex++) { s_LightSphereArray[sphereIndex].InitializeSphere(vertexAttributes, 0.2, 4); s_LightSphereArray[sphereIndex].SetWorldPosition(0.0f, 0.0f, 0.0f); s_LightSphereArray[sphereIndex].SetWorldAngle(0.0f, 0.0f, 0.0f); } u32 sphereIndex = 0; s_LightSphereArray[sphereIndex].SetColor(1.0f, 0.0f, 0.0f); sphereIndex = 1; s_LightSphereArray[sphereIndex].SetColor(0.0f, 1.0f, 0.0f); sphereIndex = 2; s_LightSphereArray[sphereIndex].SetColor(0.0f, 0.0f, 1.0f); sphereIndex = 3; s_LightSphereArray[sphereIndex].SetColor(1.0f, 1.0f, 0.0f); } void InitializeLights(void) { for (u32 lightIndex = 0; lightIndex < MAX_LIGHT_NUM; lightIndex++) { s_LightArray[lightIndex].Initialize(); } s_LightPhi[0] = 0.0f; s_LightPhi[1] = 180.0f; s_LightPhi[2] = 270.0f; s_LightPhi[3] = 0.0f; // Light0 (Red) u32 lightIndex = 0; s_LightArray[lightIndex].m_Ambient[0] = 0.0f; s_LightArray[lightIndex].m_Ambient[1] = 0.0f; s_LightArray[lightIndex].m_Ambient[2] = 0.0f; s_LightArray[lightIndex].m_Ambient[3] = 1.0f; s_LightArray[lightIndex].m_Diffuse[0] = 1.0f; s_LightArray[lightIndex].m_Diffuse[1] = 0.0f; s_LightArray[lightIndex].m_Diffuse[2] = 0.0f; s_LightArray[lightIndex].m_Diffuse[3] = 1.0f; s_LightArray[lightIndex].m_Specular0[0] = 1.0f; s_LightArray[lightIndex].m_Specular0[1] = 1.0f; s_LightArray[lightIndex].m_Specular0[2] = 1.0f; s_LightArray[lightIndex].m_Specular0[3] = 1.0f; // Light1 (Green) lightIndex = 1; s_LightArray[lightIndex].m_Ambient[0] = 0.0f; s_LightArray[lightIndex].m_Ambient[1] = 0.0f; s_LightArray[lightIndex].m_Ambient[2] = 0.0f; s_LightArray[lightIndex].m_Ambient[3] = 1.0f; s_LightArray[lightIndex].m_Diffuse[0] = 0.0f; s_LightArray[lightIndex].m_Diffuse[1] = 1.0f; s_LightArray[lightIndex].m_Diffuse[2] = 0.0f; s_LightArray[lightIndex].m_Diffuse[3] = 1.0f; s_LightArray[lightIndex].m_Specular0[0] = 1.0f; s_LightArray[lightIndex].m_Specular0[1] = 1.0f; s_LightArray[lightIndex].m_Specular0[2] = 1.0f; s_LightArray[lightIndex].m_Specular0[3] = 1.0f; // Light2 (Blue) lightIndex = 2; s_LightArray[lightIndex].m_Ambient[0] = 0.0f; s_LightArray[lightIndex].m_Ambient[1] = 0.0f; s_LightArray[lightIndex].m_Ambient[2] = 0.0f; s_LightArray[lightIndex].m_Ambient[3] = 1.0f; s_LightArray[lightIndex].m_Diffuse[0] = 0.0f; s_LightArray[lightIndex].m_Diffuse[1] = 0.0f; s_LightArray[lightIndex].m_Diffuse[2] = 1.0f; s_LightArray[lightIndex].m_Diffuse[3] = 1.0f; s_LightArray[lightIndex].m_Specular0[0] = 1.0f; s_LightArray[lightIndex].m_Specular0[1] = 1.0f; s_LightArray[lightIndex].m_Specular0[2] = 1.0f; s_LightArray[lightIndex].m_Specular0[3] = 1.0f; // Light3 (Yellow) lightIndex = 3; s_LightArray[lightIndex].m_Ambient[0] = 0.0f; s_LightArray[lightIndex].m_Ambient[1] = 0.0f; s_LightArray[lightIndex].m_Ambient[2] = 0.0f; s_LightArray[lightIndex].m_Ambient[3] = 1.0f; s_LightArray[lightIndex].m_Diffuse[0] = 1.0f; s_LightArray[lightIndex].m_Diffuse[1] = 1.0f; s_LightArray[lightIndex].m_Diffuse[2] = 0.0f; s_LightArray[lightIndex].m_Diffuse[3] = 1.0f; s_LightArray[lightIndex].m_Specular0[0] = 1.0f; s_LightArray[lightIndex].m_Specular0[1] = 1.0f; s_LightArray[lightIndex].m_Specular0[2] = 1.0f; s_LightArray[lightIndex].m_Specular0[3] = 1.0f; } void InitializeShader(void) { s_ProgramId = glCreateProgram(); // Load vertex shader 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, "aColor"); glBindAttribLocation(s_ProgramId, 2, "aNormal"); glLinkProgram(s_ProgramId); glValidateProgram(s_ProgramId); demo::InitializeUniforms(s_ProgramId); InitializeD0Lut(s_MaterialShininess); } void InitializeD0Lut(const u32& materialShininess) { const u32 LUT_TABLE_SIZE = 512; const u32 LUT_TABLE_HALF_SIZE = LUT_TABLE_SIZE / 2; GLfloat lutArray[LUT_TABLE_SIZE]; for (u32 index = 0; index < LUT_TABLE_SIZE; index++) { lutArray[index] = 0.0f; } for (u32 j = 0; j < LUT_TABLE_HALF_SIZE; j++) { f32 value = 1.0f; for (u32 count = 0; count < materialShininess; count++) { value *= (j / 255.0f); } lutArray[j] = value; } for (u32 j = 0; j < (LUT_TABLE_HALF_SIZE - 1); j++) { lutArray[j + LUT_TABLE_HALF_SIZE] = lutArray[j + 1] - lutArray[j]; } lutArray[(LUT_TABLE_HALF_SIZE - 1) + LUT_TABLE_HALF_SIZE] = 1.0f - lutArray[LUT_TABLE_HALF_SIZE - 1]; glGenTextures(1, &s_D0LutTextureId); glBindTexture(GL_LUT_TEXTURE0_DMP, s_D0LutTextureId); glTexImage1D(GL_LUT_TEXTURE0_DMP, 0, GL_LUMINANCEF_DMP, LUT_TABLE_SIZE, 0, GL_LUMINANCEF_DMP, GL_FLOAT, lutArray); } void Finalize(void) { s_Cube.Finalize(); for (u32 sphereIndex = 0; sphereIndex < MAX_SPHERE_NUM; sphereIndex++) { s_LightSphereArray[sphereIndex].Finalize(); } glDeleteTextures(1, &s_D0LutTextureId); s_RenderSystem.Finalize(); s_AppHeap.Free(reinterpret_cast(s_AddrForGxHeap)); s_AppHeap.Finalize(); } bool DrawFrame(void) { UpdateCamera(); UpdateLights(); DrawDisplay0(); DrawDisplay1(); s_RenderSystem.WaitVsync(NN_GX_DISPLAY_BOTH); return true; } void UpdateCamera(void) { nn::math::MTX34LookAt(&s_ViewMatrix, s_CameraPosition, s_CameraUp, s_CameraTarget); } void UpdateLights(void) { // Light0 (Red) u32 lightIndex = 0; f32 sinPhi = 0.0f; f32 cosPhi = 0.0f; nn::math::SinCosDeg(&sinPhi, &cosPhi, s_LightPhi[0]); s_LightArray[lightIndex].m_Position[0] = 0.0f; s_LightArray[lightIndex].m_Position[1] = s_LightRadius * cosPhi; s_LightArray[lightIndex].m_Position[2] = s_LightRadius * sinPhi; // Light1 (Green) lightIndex = 1; nn::math::SinCosDeg(&sinPhi, &cosPhi, s_LightPhi[1]); s_LightArray[lightIndex].m_Position[0] = s_LightRadius * cosPhi; s_LightArray[lightIndex].m_Position[1] = 0.0f; s_LightArray[lightIndex].m_Position[2] = s_LightRadius * sinPhi; // Light2 (Blue) lightIndex = 2; nn::math::SinCosDeg(&sinPhi, &cosPhi, s_LightPhi[2]); s_LightArray[lightIndex].m_Position[0] = s_LightRadius * cosPhi; s_LightArray[lightIndex].m_Position[1] = s_LightRadius * sinPhi; s_LightArray[lightIndex].m_Position[2] = 0.0f; // Light3 (Yellow) lightIndex = 3; nn::math::SinCosDeg(&sinPhi, &cosPhi, s_LightPhi[3]); s_LightArray[lightIndex].m_Position[0] = s_LightRadius * cosPhi; s_LightArray[lightIndex].m_Position[1] = 0.0f; s_LightArray[lightIndex].m_Position[2] = s_LightRadius * sinPhi; for (u32 index = 0; index < MAX_LIGHT_NUM; index++) { s_LightSphereArray[index].SetWorldPosition(s_LightArray[index].m_Position[0], s_LightArray[index].m_Position[1], s_LightArray[index].m_Position[2]); s_LightPhi[index] += s_LightDeltaPhi; if ( s_LightPhi[index] > 360.0f ) { s_LightPhi[index] -= 360.0f; } } } void DrawDisplay0(void) { s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY0); s_RenderSystem.Clear(); UseShader(); glUniformMatrix4fv(demo::s_UniformLocations[demo::VERTEX_UNIFORM_PROJECTION], 1, GL_TRUE, static_cast(s_Display0ProjectionMatrix)); UpdateBody(s_Cube); DrawBody(s_Cube); SetLightUniform(); DrawLights(); s_RenderSystem.SwapBuffers(); } void UseShader(void) { glUseProgram(s_ProgramId); // Fragment uniform glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_ALPHA_TEST], GL_FALSE); // Fragment uniform : Texture samplerType glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXTURE0_SAMPLER_TYPE], GL_FALSE); glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXTURE1_SAMPLER_TYPE], GL_FALSE); glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXTURE2_SAMPLER_TYPE], GL_FALSE); glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXTURE3_SAMPLER_TYPE], GL_FALSE); // LightEnv glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_LIGHT_ENV_CONFIG], GL_LIGHT_ENV_LAYER_CONFIG0_DMP); glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_LIGHT_ENV_LUT_ENABLED_REFL], GL_FALSE); glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_LIGHT_ENV_CLAMP_HIGHLIGHTS], GL_TRUE); // D0 glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_LIGHT_ENV_LUT_ENABLED_D0], GL_TRUE); glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_LIGHT_ENV_ABS_LUT_INPUT_D0], GL_TRUE); glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_LIGHT_ENV_LUT_INPUT_D0], GL_LIGHT_ENV_NH_DMP); glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_MATERIAL_SAMPLER_D0], 0); // Fragment uniform : Fragment lighting glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHTING_ENABLED], GL_TRUE); glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHTING_AMBIENT], 1, s_GlobalAmbientLight); // Light0 (Red) u32 lightIndex = 0; glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE0_ENABLED], GL_TRUE); glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE0_AMBIENT], 1, s_LightArray[lightIndex].m_Ambient); glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE0_DIFFUSE], 1, s_LightArray[lightIndex].m_Diffuse); glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE0_SPECULAR0], 1, s_LightArray[lightIndex].m_Specular0); glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE0_SPECULAR1], 1, s_LightArray[lightIndex].m_Specular1); // Compute Light0 view matrix nn::math::MTX34 s_LightWorldMatrix; nn::math::MTX34Identity(&s_LightWorldMatrix); nn::math::VEC3 position(s_LightArray[lightIndex].m_Position[0], s_LightArray[lightIndex].m_Position[1], s_LightArray[lightIndex].m_Position[2]); nn::math::MTX34Translate(&s_LightWorldMatrix, &position); nn::math::Matrix34 lightViewMatrix; nn::math::MTX34Mult(&lightViewMatrix, s_ViewMatrix, s_LightWorldMatrix); glUniform4f(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE0_POSITION], lightViewMatrix.m[0][3], lightViewMatrix.m[1][3], lightViewMatrix.m[2][3], 1.0f); glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE0_GEOM_FACTOR1], GL_FALSE); glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE0_GEOM_FACTOR0], GL_FALSE); glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE0_TWO_SIDE_DIFFUSE], GL_FALSE); // Light1 (Green) lightIndex = 1; glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE1_ENABLED], GL_TRUE); glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE1_AMBIENT], 1, s_LightArray[lightIndex].m_Ambient); glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE1_DIFFUSE], 1, s_LightArray[lightIndex].m_Diffuse); glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE1_SPECULAR0], 1, s_LightArray[lightIndex].m_Specular0); glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE1_SPECULAR1], 1, s_LightArray[lightIndex].m_Specular1); // Compute Light1 view matrix nn::math::MTX34Identity(&s_LightWorldMatrix); position.x = s_LightArray[lightIndex].m_Position[0]; position.y = s_LightArray[lightIndex].m_Position[1]; position.z = s_LightArray[lightIndex].m_Position[2]; nn::math::MTX34Translate(&s_LightWorldMatrix, &position); nn::math::MTX34Mult(&lightViewMatrix, s_ViewMatrix, s_LightWorldMatrix); glUniform4f(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE1_POSITION], lightViewMatrix.m[0][3], lightViewMatrix.m[1][3], lightViewMatrix.m[2][3], 1.0f); glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE1_GEOM_FACTOR1], GL_FALSE); glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE1_GEOM_FACTOR0], GL_FALSE); glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE1_TWO_SIDE_DIFFUSE], GL_FALSE); // Light2 (Blue) lightIndex = 2; glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE2_ENABLED], GL_TRUE); glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE2_AMBIENT], 1, s_LightArray[lightIndex].m_Ambient); glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE2_DIFFUSE], 1, s_LightArray[lightIndex].m_Diffuse); glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE2_SPECULAR0], 1, s_LightArray[lightIndex].m_Specular0); glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE2_SPECULAR1], 1, s_LightArray[lightIndex].m_Specular1); // Compute Light2 view matrix nn::math::MTX34Identity(&s_LightWorldMatrix); position.x = s_LightArray[lightIndex].m_Position[0]; position.y = s_LightArray[lightIndex].m_Position[1]; position.z = s_LightArray[lightIndex].m_Position[2]; nn::math::MTX34Translate(&s_LightWorldMatrix, &position); nn::math::MTX34Mult(&lightViewMatrix, s_ViewMatrix, s_LightWorldMatrix); glUniform4f(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE2_POSITION], lightViewMatrix.m[0][3], lightViewMatrix.m[1][3], lightViewMatrix.m[2][3], 1.0f); glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE2_GEOM_FACTOR1], GL_FALSE); glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE2_GEOM_FACTOR0], GL_FALSE); glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE2_TWO_SIDE_DIFFUSE], GL_FALSE); // Light3 (Yellow) lightIndex = 3; glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE3_ENABLED], GL_TRUE); glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE3_AMBIENT], 1, s_LightArray[lightIndex].m_Ambient); glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE3_DIFFUSE], 1, s_LightArray[lightIndex].m_Diffuse); glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE3_SPECULAR0], 1, s_LightArray[lightIndex].m_Specular0); glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE3_SPECULAR1], 1, s_LightArray[lightIndex].m_Specular1); // Compute Light3 view matrix nn::math::MTX34Identity(&s_LightWorldMatrix); position.x = s_LightArray[lightIndex].m_Position[0]; position.y = s_LightArray[lightIndex].m_Position[1]; position.z = s_LightArray[lightIndex].m_Position[2]; nn::math::MTX34Translate(&s_LightWorldMatrix, &position); nn::math::MTX34Mult(&lightViewMatrix, s_ViewMatrix, s_LightWorldMatrix); glUniform4f(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE3_POSITION], lightViewMatrix.m[0][3], lightViewMatrix.m[1][3], lightViewMatrix.m[2][3], 1.0f); glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE3_GEOM_FACTOR1], GL_FALSE); glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE3_GEOM_FACTOR0], GL_FALSE); glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE3_TWO_SIDE_DIFFUSE], GL_FALSE); // Fragment uniform : Material glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_MATERIAL_AMBIENT], 1, s_MaterialAmbient); glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_MATERIAL_DIFFUSE], 1, s_MaterialDiffuse); glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_MATERIAL_SPECULAR0], 1, s_MaterialSpecular0); glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_MATERIAL_SPECULAR1], 1, s_MaterialSpecular1); // Fragment uniform : Texture combiner glUniform3i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_SRC_RGB], GL_FRAGMENT_PRIMARY_COLOR_DMP, GL_FRAGMENT_SECONDARY_COLOR_DMP, GL_PREVIOUS); glUniform3i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_SRC_ALPHA], GL_FRAGMENT_PRIMARY_COLOR_DMP, GL_FRAGMENT_SECONDARY_COLOR_DMP, GL_PREVIOUS); glUniform3i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_OPERAND_RGB], GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_COLOR); glUniform3i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_OPERAND_ALPHA], GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA); glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_COMBINE_RGB], GL_ADD); glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_COMBINE_ALPHA], GL_ADD); } void DrawDisplay1(void) { s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY1); s_RenderSystem.Clear(); s_RenderSystem.SwapBuffers(); } void UpdateBody(demo::Body& body) { f32 worldAngle[3]; body.GetWorldAngle(worldAngle[0], worldAngle[1], worldAngle[2]); worldAngle[1] += 1.0f; if ( worldAngle[1] > 360.0f ) { worldAngle[1] = 0.0f; } body.SetWorldAngle(worldAngle[0], worldAngle[1], worldAngle[2]); } void DrawBody(demo::Body& body) { nn::math::MTX44 modelViewMatrix(s_ViewMatrix); nn::math::Matrix44 worldMatrix = body.GetWorldMatrix(); nn::math::MTX44Mult(&modelViewMatrix, &modelViewMatrix, &worldMatrix); glUniformMatrix4fv(demo::s_UniformLocations[demo::VERTEX_UNIFORM_MODELVIEW], 1, GL_TRUE, static_cast(modelViewMatrix)); body.Draw(); } void SetLightUniform(void) { glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHTING_ENABLED], GL_FALSE); // Fragment uniform : Texture combiner glUniform3i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_SRC_RGB], GL_PRIMARY_COLOR, GL_PRIMARY_COLOR, GL_PREVIOUS); glUniform3i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_SRC_ALPHA], GL_PRIMARY_COLOR, GL_PRIMARY_COLOR, GL_PREVIOUS); glUniform3i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_OPERAND_RGB], GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_COLOR); glUniform3i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_OPERAND_ALPHA], GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA); glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_COMBINE_RGB], GL_REPLACE); glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_COMBINE_ALPHA], GL_REPLACE); } void DrawLights(void) { for (u32 lightIndex = 0; lightIndex < MAX_LIGHT_NUM; lightIndex++) { DrawBody(s_LightSphereArray[lightIndex]); } } 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(); Initialize(); bool flag = true; while ( flag ) { flag = DrawFrame(); } Finalize(); }