/*---------------------------------------------------------------------------* Project: Horizon File: LightingDistanceAtte.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" #include "s.h" #define APP_NAME "LightingDistanceAtte" #define DMP_PI (3.1415926f) #define REV_PI (1.0f/DMP_PI) /* buffer id */ GLuint s_ArrayBufferID; GLuint s_ElementArrayBufferID; /* program id */ GLuint s_ProgramID; /* shader id */ GLuint s_ShaderID; /* sphere object */ sphere *obj = 0; /* ExpHeap for app. */ nn::fnd::ExpHeap s_AppHeap; uptr s_HeapForGx; uptr s_HeapForMalloc; const u32 s_GxHeapSize = 0x400000; const u32 s_HeapSize = 0x400000; demo::RenderSystem s_RenderSystem; static void SetRenderState(void) { GLfloat la[] = {1.f, 1.f, 1.f, 1.f}; GLfloat ld[] = {1.f, 1.f, 1.f, 1.f}; glUniform4fv(glGetUniformLocation(s_ProgramID, "dmp_FragmentLightSource[0].ambient"), 1, la); glUniform4fv(glGetUniformLocation(s_ProgramID, "dmp_FragmentLightSource[0].diffuse"), 1, ld); /* setup lookup table */ GLuint lutids[1]; glGenTextures(1, lutids); GLfloat lut[512]; int j; /* In this sample, the distance attenuation lookup table uses the distribution expressed by the function y=1-x */ memset(lut, 0, sizeof(lut)); for (j = 0; j < 256; j++) { float x = (float)j / 255.f; float y = 1 - x; lut[j] = y; } for (j = 0; j < 255; j++) lut[j + 256] = lut[j + 1] - lut[j]; lut[255 + 256] = 0.f - lut[255]; glBindTexture(GL_LUT_TEXTURE0_DMP, lutids[0]); glTexImage1D(GL_LUT_TEXTURE0_DMP, 0, GL_LUMINANCEF_DMP, 512, 0, GL_LUMINANCEF_DMP, GL_FLOAT, lut); glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentLightSource[0].samplerDA"), 0); glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentLightSource[0].distanceAttenuationEnabled"), GL_TRUE ); /* Regarding scale and bias for the lookup table input values, typically, if "start" is used as the attenuation start distance and "end" is used as the attenuation end distance, and if scale is set to "1.0/(end - start)" and bias is set to "-start/(end - start)" then "start" and "end" would be mapped to input values of 0.0 and 1.0. However, in this sample, those values may not always be used. */ glUniform1f(glGetUniformLocation(s_ProgramID, "dmp_FragmentLightSource[0].distanceAttenuationScale"), 0.07f ); glUniform1f(glGetUniformLocation(s_ProgramID, "dmp_FragmentLightSource[0].distanceAttenuationBias"), 0.f ); } /* generate simple object */ static void LoadObjects(void) { obj = new sphere(20, 20, 1.f); glGenBuffers(1, &s_ArrayBufferID); glBindBuffer(GL_ARRAY_BUFFER, s_ArrayBufferID); glBufferData(GL_ARRAY_BUFFER, obj->get_index_count()*3*sizeof(float)*2, 0, GL_STATIC_DRAW); glBufferSubData(GL_ARRAY_BUFFER, 0, obj->get_index_count()*3*sizeof(float), obj->get_vertex()); glBufferSubData(GL_ARRAY_BUFFER, obj->get_index_count()*3*sizeof(float), obj->get_index_count()*3*sizeof(float), obj->get_normal()); glGenBuffers(1, &s_ElementArrayBufferID); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s_ElementArrayBufferID); glBufferData(GL_ELEMENT_ARRAY_BUFFER, obj->get_index_count()*sizeof(unsigned short), obj->get_index(), GL_STATIC_DRAW); glEnableVertexAttribArray(0); glEnableVertexAttribArray(1); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)(obj->get_index_count()*3*sizeof(float))); } static void UnloadObjects(void) { glDeleteBuffers(1, &s_ArrayBufferID); glDeleteBuffers(1, &s_ElementArrayBufferID); delete obj; return; } void DrawSphere() { glBindBuffer(GL_ARRAY_BUFFER, s_ArrayBufferID); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s_ElementArrayBufferID); glDrawElements(GL_TRIANGLES, obj->get_index_count(), GL_UNSIGNED_SHORT, 0); } int DrawFrame(void) { static int f = 0; nn::math::Matrix34 mv, rot; s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY0); s_RenderSystem.Clear(); /* setup projection matrix */ nn::math::Matrix44 proj; 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, 15.f, 20.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, 0.f, 0.f, 1.f); lpos0.y = 5.f * cosf(2.f * f / 60.f) + 7.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(VEC4Dot(&mv0, &lpos0), VEC4Dot(&mv1, &lpos0), VEC4Dot(&mv2, &lpos0), lpos0.w); glUniform4fv(glGetUniformLocation(s_ProgramID, "dmp_FragmentLightSource[0].position"), 1, static_cast(lpos)); GLfloat sphere_a[] = {0.f, 0.f, 0.f, 1.f}; GLfloat sphere_d[] = {1.f, 1.f, 0.f, 1.f}; glUniform4fv(glGetUniformLocation(s_ProgramID, "dmp_FragmentMaterial.ambient"), 1, sphere_a); glUniform4fv(glGetUniformLocation(s_ProgramID, "dmp_FragmentMaterial.diffuse"), 1, sphere_d); #define N ( 3 ) for (unsigned k = 0; k < N*2+1; k++) { for (unsigned j = 0; j < N*2+1; j++) { float x = -3.f*N + (float)k*N; float z = -3.f*N + (float)j*N; nn::math::Vector3 trans(x, 0.0f, z); nn::math::Matrix34 mv_tr, tmp; nn::math::MTX34Translate(&tmp, &trans); MTX34Mult(&mv_tr, &mv, &tmp); nn::math::Matrix44 m(mv_tr); glUniformMatrix4fv(glGetUniformLocation(s_ProgramID, "uModelView"), 1, GL_TRUE, static_cast(m)); DrawSphere(); } } /* draw light object */ GLfloat light_a[] = {1.f, 0.f, 0.f, 1.f}; GLfloat light_d[] = {0.f, 0.f, 0.f, 1.f}; glUniform4fv(glGetUniformLocation(s_ProgramID, "dmp_FragmentMaterial.ambient"), 1, light_a); glUniform4fv(glGetUniformLocation(s_ProgramID, "dmp_FragmentMaterial.diffuse"), 1, light_d); { nn::math::Matrix34 mv_tr, tmp[2]; nn::math::Vector3 trans(lpos0.x, lpos0.y, lpos0.z); nn::math::Vector3 scale(0.3f, 0.3f, 0.3f); nn::math::MTX34Translate(&tmp[0], &trans); nn::math::MTX34Scale(&tmp[1], &scale); nn::math::MTX34Mult(&mv_tr, &mv, &tmp[0]); nn::math::MTX34Mult(&mv_tr, &mv_tr, &tmp[1]); nn::math::Matrix44 m(mv_tr); glUniformMatrix4fv(glGetUniformLocation(s_ProgramID, "uModelView"), 1, GL_TRUE, static_cast(m)); DrawSphere(); } 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_HeapSize); 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 */ SetRenderState(); /* enable DMP fragment lighting */ glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentLighting.enabled"), GL_TRUE); glUniform1i(glGetUniformLocation(s_ProgramID, "dmp_FragmentLightSource[0].enabled"), GL_TRUE); /* this sample use only fragment primary color */ 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_PRIMARY_COLOR_DMP, GL_CONSTANT, GL_CONSTANT); glUniform3i(glGetUniformLocation(s_ProgramID, "dmp_TexEnv[0].srcAlpha"), GL_CONSTANT, GL_CONSTANT, GL_CONSTANT); 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(); }