/*---------------------------------------------------------------------------* Project: Horizon File: gx_VertexBuffer.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 { // Specify whether the vertex buffer and the index buffer are copied into main memory as well as whether they are allocated in main memory, VRAMA, or VRAMB. // // // enum { // (a) When there is a copy to main memory and when PICA accesses the copy in main memory USE_VBO_MEM_MAIN_COPY = 0, // (b) When there is no copy in main memory and PICA directly accesses main memory USE_VBO_MEM_MAIN_NO_COPY, // (c) When there is a copy in main memory and PICA accesses VRAMA // Sends data from the copy in main memory to VRAMA using DMA transfer, and PICA accesses that VRAMA. USE_VBO_VRAMA_COPY, // (d) When there is no copy in main memory and PICA accesses VRAMA // Sends data from main memory to VRAMA using DMA transfer, and PICA accesses that VRAMA. USE_VBO_VRAMA_NO_COPY, // (e) When there is a copy in main memory and PICA accesses VRAMB // Sends data from the copy in main memory to VRAMB using DMA transfer, and PICA accesses that VRAMB. USE_VBO_VRAMB_COPY, // (f) When there is no copy in main memory and PICA accesses VRAMB // Sends data from main memory to VRAMB using DMA transfer, and PICA accesses that VRAMB. USE_VBO_VRAMB_NO_COPY }; u32 s_VertexBufferPattern = USE_VBO_MEM_MAIN_COPY; // u32 s_VertexBufferPattern = USE_VBO_MEM_MAIN_NO_COPY; // u32 s_VertexBufferPattern = USE_VBO_VRAMA_COPY; // u32 s_VertexBufferPattern = USE_VBO_VRAMA_NO_COPY; // u32 s_VertexBufferPattern = USE_VBO_VRAMB_COPY; // u32 s_VertexBufferPattern = USE_VBO_VRAMB_NO_COPY; GLenum s_ArrayBufferDataType = GL_ARRAY_BUFFER; GLenum s_ElementArrayBufferDataType = GL_ELEMENT_ARRAY_BUFFER; 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, 2.0f, 2.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; f32 s_GlobalAmbientLight[] = { 0.3f, 0.3f, 0.3f, 1.0f}; f32 s_Light0Ambient[] = { 0.3f, 0.3f, 0.3f, 1.0f}; f32 s_Light0Diffuse[] = { 0.7f, 0.7f, 0.7f, 1.0f}; f32 s_Light0Position[] = { 10.0f, 10.0f, 10.0f, 1.0f}; f32 s_MaterialAmbient[] = {0.3f, 0.3f, 0.3f, 1.0f}; f32 s_MaterialDiffuse[] = {0.7f, 0.7f, 0.7f, 1.0f}; const u32 VERTEX_POSITION_ATTRIBUTE_INDEX = 0; const u32 VERTEX_COLOR_ATTRIBUTE_INDEX = 1; const u32 VERTEX_NORMAL_ATTRIBUTE_INDEX = 2; const u32 VERTEX_ATTRIBUTES_NUM = 3; const u32 VERTEX_POSITION_ATTRIBUTE_SIZE = 4; const u32 VERTEX_COLOR_ATTRIBUTE_SIZE = 4; const u32 VERTEX_NORMAL_ATTRIBUTE_SIZE = 3; const u32 s_VerticesNum = 24; const u32 s_TrianglesNum = 12; const u32 s_PositionArraySize = s_VerticesNum * VERTEX_POSITION_ATTRIBUTE_SIZE * 4; const u32 s_ColorArraySize = s_VerticesNum * VERTEX_COLOR_ATTRIBUTE_SIZE * 4; const u32 s_NormalArraySize = s_VerticesNum * VERTEX_NORMAL_ATTRIBUTE_SIZE * 4; const u32 s_IndexArraySize = s_TrianglesNum * 3 * 2; GLfloat* s_PositionArray = NULL; GLfloat* s_ColorArray = NULL; GLfloat* s_NormalArray = NULL; GLushort* s_IndexArray = NULL; GLuint s_ArrayBufferIdArray[3]; GLuint s_ElementArrayBufferId = 0; f32 s_CubeHalfEdge[3]; nn::math::MTX44 s_WorldMatrix; f32 s_Position[3]; f32 s_Angle[3]; } void InitializeGraphics(void); void InitializeCube(void); void InitializeShader(void); void AllocateCube(void); void SetCube(void); void UpdateCubeVBO(const bool& updatePosition=true, const bool& updateColor=true, const bool& updateNormal=true, const bool& updateIndex=true); void SetCubePosition(void); void SetCubeColor(const f32& red, const f32& green, const f32& blue, const f32& alpha); void SetCubeNormal(void); void SetCubeIndex(void); void FinalizeCube(void); void DeallocateCube(void); void UseShader(void); void UpdateCamera(void); void DrawDisplay0(void); void DrawDisplay1(void); void UpdateCube(void); void DrawCube(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); // Stops executing the command list. nngxStopCmdlist(); glClearColor(0.3f, 0.3f, 0.3f, 1.0f); glClearDepthf(1.f); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LESS); glEnable(GL_CULL_FACE); glFrontFace(GL_CCW); glCullFace(GL_BACK); InitializeShader(); // Initialize projection matrix nn::math::MTX44PerspectivePivotDeg(&s_Display0ProjectionMatrix, 45.0f, demo::DISPLAY0_ASPECT, 0.2f, 100.0f, nn::math::PIVOT_UPSIDE_TO_TOP); nn::math::MTX44PerspectivePivotDeg(&s_Display1ProjectionMatrix, 45.0f, demo::DISPLAY1_ASPECT, 0.2f, 100.0f, nn::math::PIVOT_UPSIDE_TO_TOP); InitializeCube(); NN_LOG("Update vertex color to RED->GREEN->BLUE.\n"); } 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, VERTEX_POSITION_ATTRIBUTE_INDEX, "aPosition"); glBindAttribLocation(s_ProgramId, VERTEX_COLOR_ATTRIBUTE_INDEX, "aColor"); glBindAttribLocation(s_ProgramId, VERTEX_NORMAL_ATTRIBUTE_INDEX, "aNormal"); glLinkProgram(s_ProgramId); glValidateProgram(s_ProgramId); demo::InitializeUniforms(s_ProgramId); } void InitializeCube(void) { // (a) When there is a copy to main memory and when PICA accesses the copy in main memory if ( s_VertexBufferPattern == USE_VBO_MEM_MAIN_COPY ) { s_ArrayBufferDataType = GL_ARRAY_BUFFER | NN_GX_MEM_FCRAM | GL_COPY_FCRAM_DMP; s_ElementArrayBufferDataType = GL_ELEMENT_ARRAY_BUFFER | NN_GX_MEM_FCRAM | GL_COPY_FCRAM_DMP; NN_LOG("Allocate the vertex buffer in main memory with COPY.\n"); NN_LOG(" GL_ARRAY_BUFFER | NN_GX_MEM_FCRAM | GL_COPY_FCRAM_DMP\n"); NN_LOG(" GL_ELEMENT_ARRAY_BUFFER | NN_GX_MEM_FCRAM | GL_COPY_FCRAM_DMP\n"); } // (b) When there is no copy in main memory and PICA directly accesses main memory else if ( s_VertexBufferPattern == USE_VBO_MEM_MAIN_NO_COPY ) { s_ArrayBufferDataType = GL_ARRAY_BUFFER | NN_GX_MEM_FCRAM | GL_NO_COPY_FCRAM_DMP; s_ElementArrayBufferDataType = GL_ELEMENT_ARRAY_BUFFER | NN_GX_MEM_FCRAM | GL_NO_COPY_FCRAM_DMP; NN_LOG("Allocate the vertex buffer in main memory with NO_COPY.\n"); NN_LOG(" GL_ARRAY_BUFFER | NN_GX_MEM_FCRAM | GL_NO_COPY_FCRAM_DMP\n"); NN_LOG(" GL_ELEMENT_ARRAY_BUFFER | NN_GX_MEM_FCRAM | GL_NO_COPY_FCRAM_DMP\n"); } // (c) When there is a copy in main memory and PICA accesses VRAMA else if ( s_VertexBufferPattern == USE_VBO_VRAMA_COPY ) { s_ArrayBufferDataType = GL_ARRAY_BUFFER | NN_GX_MEM_VRAMA | GL_COPY_FCRAM_DMP; s_ElementArrayBufferDataType = GL_ELEMENT_ARRAY_BUFFER | NN_GX_MEM_VRAMA | GL_COPY_FCRAM_DMP; NN_LOG("Allocate the vertex buffer in VRAMA with FCRAM COPY.\n"); NN_LOG(" GL_ARRAY_BUFFER | NN_GX_MEM_VRAMA | GL_COPY_FCRAM_DMP\n"); NN_LOG(" GL_ELEMENT_ARRAY_BUFFER | NN_GX_MEM_VRAMA | GL_COPY_FCRAM_DMP\n"); } // (d) When there is no copy in main memory and PICA accesses VRAMA else if ( s_VertexBufferPattern == USE_VBO_VRAMA_NO_COPY ) { s_ArrayBufferDataType = GL_ARRAY_BUFFER | NN_GX_MEM_VRAMA | GL_NO_COPY_FCRAM_DMP; s_ElementArrayBufferDataType = GL_ELEMENT_ARRAY_BUFFER | NN_GX_MEM_VRAMA | GL_NO_COPY_FCRAM_DMP; NN_LOG("Allocate the vertex buffer in VRAMA with FCRAM NO_COPY.\n"); NN_LOG(" GL_ARRAY_BUFFER | NN_GX_MEM_VRAMA | GL_NO_COPY_FCRAM_DMP\n"); NN_LOG(" GL_ELEMENT_ARRAY_BUFFER | NN_GX_MEM_VRAMA | GL_NO_COPY_FCRAM_DMP\n"); } // (e) When there is a copy in main memory and PICA accesses VRAMB else if ( s_VertexBufferPattern == USE_VBO_VRAMB_COPY ) { s_ArrayBufferDataType = GL_ARRAY_BUFFER | NN_GX_MEM_VRAMB | GL_COPY_FCRAM_DMP; s_ElementArrayBufferDataType = GL_ELEMENT_ARRAY_BUFFER | NN_GX_MEM_VRAMB | GL_COPY_FCRAM_DMP; NN_LOG("Allocate the vertex buffer in VRAMB with FCRAM COPY.\n"); NN_LOG(" GL_ARRAY_BUFFER | NN_GX_MEM_VRAMB | GL_COPY_FCRAM_DMP\n"); NN_LOG(" GL_ELEMENT_ARRAY_BUFFER | NN_GX_MEM_VRAMB | GL_COPY_FCRAM_DMP\n"); } // (f) When there is no copy in main memory and PICA accesses VRAMB else if ( s_VertexBufferPattern == USE_VBO_VRAMB_NO_COPY ) { s_ArrayBufferDataType = GL_ARRAY_BUFFER | NN_GX_MEM_VRAMB | GL_NO_COPY_FCRAM_DMP; s_ElementArrayBufferDataType = GL_ELEMENT_ARRAY_BUFFER | NN_GX_MEM_VRAMB | GL_NO_COPY_FCRAM_DMP; NN_LOG("Allocate the vertex buffer in VRAMB with FCRAM NO_COPY.\n"); NN_LOG(" GL_ARRAY_BUFFER | NN_GX_MEM_VRAMB | GL_NO_COPY_FCRAM_DMP\n"); NN_LOG(" GL_ELEMENT_ARRAY_BUFFER | NN_GX_MEM_VRAMB | GL_NO_COPY_FCRAM_DMP\n"); } // Allocates the arrays for vertex data and indices AllocateCube(); SetCube(); // Generates the vertex buffer for (u32 index = 0; index < 3; index++) { s_ArrayBufferIdArray[index] = 0; } glGenBuffers(3, s_ArrayBufferIdArray); if ( s_ArrayBufferIdArray == NULL ) { NN_PANIC("FILE(%s), LINE(%d) : s_ArrayBufferIdArray is 0.\n", __FILE__, __LINE__); } // POSITION : Allocates the vertex buffer glBindBuffer(GL_ARRAY_BUFFER, s_ArrayBufferIdArray[VERTEX_POSITION_ATTRIBUTE_INDEX]); glBufferData(s_ArrayBufferDataType, s_PositionArraySize, s_PositionArray, GL_STATIC_DRAW); // COLOR Allocates the vertex buffer glBindBuffer(GL_ARRAY_BUFFER, s_ArrayBufferIdArray[VERTEX_COLOR_ATTRIBUTE_INDEX]); glBufferData(s_ArrayBufferDataType, s_ColorArraySize, s_ColorArray, GL_STATIC_DRAW); // NORMAL : Allocates the vertex buffer glBindBuffer(GL_ARRAY_BUFFER, s_ArrayBufferIdArray[VERTEX_NORMAL_ATTRIBUTE_INDEX]); glBufferData(s_ArrayBufferDataType, s_NormalArraySize, s_NormalArray, GL_STATIC_DRAW); // Generates the index buffer glGenBuffers(1, &s_ElementArrayBufferId); if ( s_ElementArrayBufferId == 0 ) { NN_PANIC("FILE(%s), LINE(%d) : s_ElementArrayBufferId is 0.\n", __FILE__, __LINE__); } // INDEX glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s_ElementArrayBufferId); glBufferData(s_ElementArrayBufferDataType, s_IndexArraySize, s_IndexArray, GL_STATIC_DRAW); // Updates the vertex buffer and index buffer. UpdateCubeVBO(); DEMO_ASSERT_GL_ERROR(); } void AllocateCube(void) { // If there is no copy in main memory (cases (b), (d) (f)), the vertex data must be allocated from device memory. // // In this demo, all vertex data is allocated from device memory. // Allocate vertex arrays from device memory s_PositionArray = (f32*)demo::Alloc(s_PositionArraySize); if ( s_PositionArray == NULL ) { NN_PANIC("FILE(%s), LINE(%d) : s_PositionArray is NULL.\n", __FILE__, __LINE__); } s_ColorArray = (f32*)demo::Alloc(s_ColorArraySize); if ( s_ColorArray == NULL ) { NN_PANIC("FILE(%s), LINE(%d) : s_ColorArray is NULL.\n", __FILE__, __LINE__); } s_NormalArray = (f32*)demo::Alloc(s_NormalArraySize); if ( s_NormalArray == NULL ) { NN_PANIC("FILE(%s), LINE(%d) : s_NormalArray is NULL.\n", __FILE__, __LINE__); } // Allocate index arrays from device memory s_IndexArray = (GLushort*)demo::Alloc(s_IndexArraySize); if ( s_IndexArray == NULL ) { NN_PANIC("FILE(%s), LINE(%d) : s_IndexArray is NULL.\n", __FILE__, __LINE__); } } void SetCube(void) { for (u32 index = 0; index < 3; index++) { s_CubeHalfEdge[index] = 0.5f; } for (u32 index = 0; index < 3; index++) { s_Position[index] = 0.0f; s_Angle[index] = 0.0f; } SetCubePosition(); SetCubeColor(1.0f, 0.0f, 0.0f, 1.0f); SetCubeNormal(); SetCubeIndex(); } void SetCubePosition(void) { // POSITION : -Y face u32 vertexIndex = 0; s_PositionArray[4 * vertexIndex] = (- s_CubeHalfEdge[0]); s_PositionArray[4 * vertexIndex + 1] = (- s_CubeHalfEdge[1]); s_PositionArray[4 * vertexIndex + 2] = (- s_CubeHalfEdge[2]); s_PositionArray[4 * vertexIndex + 3] = 1.0f; vertexIndex++; s_PositionArray[4 * vertexIndex] = (- s_CubeHalfEdge[0]); s_PositionArray[4 * vertexIndex + 1] = (- s_CubeHalfEdge[1]); s_PositionArray[4 * vertexIndex + 2] = (+ s_CubeHalfEdge[2]); s_PositionArray[4 * vertexIndex + 3] = 1.0f; vertexIndex++; s_PositionArray[4 * vertexIndex] = (+ s_CubeHalfEdge[0]); s_PositionArray[4 * vertexIndex + 1] = (- s_CubeHalfEdge[1]); s_PositionArray[4 * vertexIndex + 2] = (+ s_CubeHalfEdge[2]); s_PositionArray[4 * vertexIndex + 3] = 1.0f; vertexIndex++; s_PositionArray[4 * vertexIndex] = (+ s_CubeHalfEdge[0]); s_PositionArray[4 * vertexIndex + 1] = (- s_CubeHalfEdge[1]); s_PositionArray[4 * vertexIndex + 2] = (- s_CubeHalfEdge[2]); s_PositionArray[4 * vertexIndex + 3] = 1.0f; vertexIndex++; // POSITION : +Y face s_PositionArray[4 * vertexIndex] = (- s_CubeHalfEdge[0]); s_PositionArray[4 * vertexIndex + 1] = (+ s_CubeHalfEdge[1]); s_PositionArray[4 * vertexIndex + 2] = (- s_CubeHalfEdge[2]); s_PositionArray[4 * vertexIndex + 3] = 1.0f; vertexIndex++; s_PositionArray[4 * vertexIndex] = (+ s_CubeHalfEdge[0]); s_PositionArray[4 * vertexIndex + 1] = (+ s_CubeHalfEdge[1]); s_PositionArray[4 * vertexIndex + 2] = (- s_CubeHalfEdge[2]); s_PositionArray[4 * vertexIndex + 3] = 1.0f; vertexIndex++; s_PositionArray[4 * vertexIndex] = (+ s_CubeHalfEdge[0]); s_PositionArray[4 * vertexIndex + 1] = (+ s_CubeHalfEdge[1]); s_PositionArray[4 * vertexIndex + 2] = (+ s_CubeHalfEdge[2]); s_PositionArray[4 * vertexIndex + 3] = 1.0f; vertexIndex++; s_PositionArray[4 * vertexIndex] = (- s_CubeHalfEdge[0]); s_PositionArray[4 * vertexIndex + 1] = (+ s_CubeHalfEdge[1]); s_PositionArray[4 * vertexIndex + 2] = (+ s_CubeHalfEdge[2]); s_PositionArray[4 * vertexIndex + 3] = 1.0f; vertexIndex++; // POSITION : -Z face s_PositionArray[4 * vertexIndex] = (- s_CubeHalfEdge[0]); s_PositionArray[4 * vertexIndex + 1] = (- s_CubeHalfEdge[1]); s_PositionArray[4 * vertexIndex + 2] = (- s_CubeHalfEdge[2]); s_PositionArray[4 * vertexIndex + 3] = 1.0f; vertexIndex++; s_PositionArray[4 * vertexIndex] = (+ s_CubeHalfEdge[0]); s_PositionArray[4 * vertexIndex + 1] = (- s_CubeHalfEdge[1]); s_PositionArray[4 * vertexIndex + 2] = (- s_CubeHalfEdge[2]); s_PositionArray[4 * vertexIndex + 3] = 1.0f; vertexIndex++; s_PositionArray[4 * vertexIndex] = (+ s_CubeHalfEdge[0]); s_PositionArray[4 * vertexIndex + 1] = (+ s_CubeHalfEdge[1]); s_PositionArray[4 * vertexIndex + 2] = (- s_CubeHalfEdge[2]); s_PositionArray[4 * vertexIndex + 3] = 1.0f; vertexIndex++; s_PositionArray[4 * vertexIndex] = (- s_CubeHalfEdge[0]); s_PositionArray[4 * vertexIndex + 1] = (+ s_CubeHalfEdge[1]); s_PositionArray[4 * vertexIndex + 2] = (- s_CubeHalfEdge[2]); s_PositionArray[4 * vertexIndex + 3] = 1.0f; vertexIndex++; // POSITION : +Z face s_PositionArray[4 * vertexIndex] = (- s_CubeHalfEdge[0]); s_PositionArray[4 * vertexIndex + 1] = (- s_CubeHalfEdge[1]); s_PositionArray[4 * vertexIndex + 2] = (+ s_CubeHalfEdge[2]); s_PositionArray[4 * vertexIndex + 3] = 1.0f; vertexIndex++; s_PositionArray[4 * vertexIndex] = (- s_CubeHalfEdge[0]); s_PositionArray[4 * vertexIndex + 1] = (+ s_CubeHalfEdge[1]); s_PositionArray[4 * vertexIndex + 2] = (+ s_CubeHalfEdge[2]); s_PositionArray[4 * vertexIndex + 3] = 1.0f; vertexIndex++; s_PositionArray[4 * vertexIndex] = (+ s_CubeHalfEdge[0]); s_PositionArray[4 * vertexIndex + 1] = (+ s_CubeHalfEdge[1]); s_PositionArray[4 * vertexIndex + 2] = (+ s_CubeHalfEdge[2]); s_PositionArray[4 * vertexIndex + 3] = 1.0f; vertexIndex++; s_PositionArray[4 * vertexIndex] = (+ s_CubeHalfEdge[0]); s_PositionArray[4 * vertexIndex + 1] = (- s_CubeHalfEdge[1]); s_PositionArray[4 * vertexIndex + 2] = (+ s_CubeHalfEdge[2]); s_PositionArray[4 * vertexIndex + 3] = 1.0f; vertexIndex++; // POSITION : -X face s_PositionArray[4 * vertexIndex] = (- s_CubeHalfEdge[0]); s_PositionArray[4 * vertexIndex + 1] = (- s_CubeHalfEdge[1]); s_PositionArray[4 * vertexIndex + 2] = (- s_CubeHalfEdge[2]); s_PositionArray[4 * vertexIndex + 3] = 1.0f; vertexIndex++; s_PositionArray[4 * vertexIndex] = (- s_CubeHalfEdge[0]); s_PositionArray[4 * vertexIndex + 1] = (+ s_CubeHalfEdge[1]); s_PositionArray[4 * vertexIndex + 2] = (- s_CubeHalfEdge[2]); s_PositionArray[4 * vertexIndex + 3] = 1.0f; vertexIndex++; s_PositionArray[4 * vertexIndex] = (- s_CubeHalfEdge[0]); s_PositionArray[4 * vertexIndex + 1] = (+ s_CubeHalfEdge[1]); s_PositionArray[4 * vertexIndex + 2] = (+ s_CubeHalfEdge[2]); s_PositionArray[4 * vertexIndex + 3] = 1.0f; vertexIndex++; s_PositionArray[4 * vertexIndex] = (- s_CubeHalfEdge[0]); s_PositionArray[4 * vertexIndex + 1] = (- s_CubeHalfEdge[1]); s_PositionArray[4 * vertexIndex + 2] = (+ s_CubeHalfEdge[2]); s_PositionArray[4 * vertexIndex + 3] = 1.0f; vertexIndex++; // POSITION : +X face s_PositionArray[4 * vertexIndex] = (+ s_CubeHalfEdge[0]); s_PositionArray[4 * vertexIndex + 1] = (- s_CubeHalfEdge[1]); s_PositionArray[4 * vertexIndex + 2] = (- s_CubeHalfEdge[2]); s_PositionArray[4 * vertexIndex + 3] = 1.0f; vertexIndex++; s_PositionArray[4 * vertexIndex] = (+ s_CubeHalfEdge[0]); s_PositionArray[4 * vertexIndex + 1] = (- s_CubeHalfEdge[1]); s_PositionArray[4 * vertexIndex + 2] = (+ s_CubeHalfEdge[2]); s_PositionArray[4 * vertexIndex + 3] = 1.0f; vertexIndex++; s_PositionArray[4 * vertexIndex] = (+ s_CubeHalfEdge[0]); s_PositionArray[4 * vertexIndex + 1] = (+ s_CubeHalfEdge[1]); s_PositionArray[4 * vertexIndex + 2] = (+ s_CubeHalfEdge[2]); s_PositionArray[4 * vertexIndex + 3] = 1.0f; vertexIndex++; s_PositionArray[4 * vertexIndex] = (+ s_CubeHalfEdge[0]); s_PositionArray[4 * vertexIndex + 1] = (+ s_CubeHalfEdge[1]); s_PositionArray[4 * vertexIndex + 2] = (- s_CubeHalfEdge[2]); s_PositionArray[4 * vertexIndex + 3] = 1.0f; vertexIndex++; } void SetCubeColor(const f32& red, const f32& green, const f32& blue, const f32& alpha) { for (u32 vertexIndex = 0; vertexIndex < s_VerticesNum; vertexIndex++) { s_ColorArray[4 * vertexIndex] = red; s_ColorArray[4 * vertexIndex + 1] = green; s_ColorArray[4 * vertexIndex + 2] = blue; s_ColorArray[4 * vertexIndex + 3] = alpha; } } void SetCubeNormal(void) { u32 vertexIndex = 0; // NORMAL : -Y face for (u32 index = 0; index < 4; index++) { s_NormalArray[3 * vertexIndex] = 0.0f; s_NormalArray[3 * vertexIndex + 1] = -1.0f; s_NormalArray[3 * vertexIndex + 2] = 0.0f; vertexIndex++; } // NORMAL : +Y face for (u32 index = 0; index < 4; index++) { s_NormalArray[3 * vertexIndex] = 0.0f; s_NormalArray[3 * vertexIndex + 1] = 1.0f; s_NormalArray[3 * vertexIndex + 2] = 0.0f; vertexIndex++; } // NORMAL : -Z face for (u32 index = 0; index < 4; index++) { s_NormalArray[3 * vertexIndex] = 0.0f; s_NormalArray[3 * vertexIndex + 1] = 0.0f; s_NormalArray[3 * vertexIndex + 2] = -1.0f; vertexIndex++; } // NORMAL : +Z face for (u32 index = 0; index < 4; index++) { s_NormalArray[3 * vertexIndex] = 0.0f; s_NormalArray[3 * vertexIndex + 1] = 0.0f; s_NormalArray[3 * vertexIndex + 2] = 1.0f; vertexIndex++; } // NORMAL : -X face for (u32 index = 0; index < 4; index++) { s_NormalArray[3 * vertexIndex] = -1.0f; s_NormalArray[3 * vertexIndex + 1] = 0.0f; s_NormalArray[3 * vertexIndex + 2] = 1.0f; vertexIndex++; } // NORMAL : +X face for (u32 index = 0; index < 4; index++) { s_NormalArray[3 * vertexIndex] = 1.0f; s_NormalArray[3 * vertexIndex + 1] = 0.0f; s_NormalArray[3 * vertexIndex + 2] = 0.0f; vertexIndex++; } } void SetCubeIndex(void) { u32 triangleIndex = 0; // INDEX : -Y face s_IndexArray[3 * triangleIndex] = 0; s_IndexArray[3 * triangleIndex + 1] = 2; s_IndexArray[3 * triangleIndex + 2] = 1; triangleIndex++; s_IndexArray[3 * triangleIndex] = 0; s_IndexArray[3 * triangleIndex + 1] = 3; s_IndexArray[3 * triangleIndex + 2] = 2; triangleIndex++; // INDEX : +Y face s_IndexArray[3 * triangleIndex] = 4; s_IndexArray[3 * triangleIndex + 1] = 6; s_IndexArray[3 * triangleIndex + 2] = 5; triangleIndex++; s_IndexArray[3 * triangleIndex] = 4; s_IndexArray[3 * triangleIndex + 1] = 7; s_IndexArray[3 * triangleIndex + 2] = 6; triangleIndex++; // INDEX : -Z face s_IndexArray[3 * triangleIndex] = 8; s_IndexArray[3 * triangleIndex + 1] = 10; s_IndexArray[3 * triangleIndex + 2] = 9; triangleIndex++; s_IndexArray[3 * triangleIndex] = 8; s_IndexArray[3 * triangleIndex + 1] = 11; s_IndexArray[3 * triangleIndex + 2] = 10; triangleIndex++; // INDEX : +Z face s_IndexArray[3 * triangleIndex] = 12; s_IndexArray[3 * triangleIndex + 1] = 14; s_IndexArray[3 * triangleIndex + 2] = 13; triangleIndex++; s_IndexArray[3 * triangleIndex] = 12; s_IndexArray[3 * triangleIndex + 1] = 15; s_IndexArray[3 * triangleIndex + 2] = 14; triangleIndex++; // INDEX : -X face s_IndexArray[3 * triangleIndex] = 16; s_IndexArray[3 * triangleIndex + 1] = 18; s_IndexArray[3 * triangleIndex + 2] = 17; triangleIndex++; s_IndexArray[3 * triangleIndex] = 16; s_IndexArray[3 * triangleIndex + 1] = 19; s_IndexArray[3 * triangleIndex + 2] = 18; triangleIndex++; // INDEX : +X face s_IndexArray[3 * triangleIndex] = 20; s_IndexArray[3 * triangleIndex + 1] = 22; s_IndexArray[3 * triangleIndex + 2] = 21; triangleIndex++; s_IndexArray[3 * triangleIndex] = 20; s_IndexArray[3 * triangleIndex + 1] = 23; s_IndexArray[3 * triangleIndex + 2] = 22; triangleIndex++; } void UpdateCubeVBO(const bool& updatePosition, const bool& updateColor, const bool& updateNormal, const bool& updateIndex) { // POSITION : Update the vertex coordinates if ( updatePosition ) { glBindBuffer(GL_ARRAY_BUFFER, s_ArrayBufferIdArray[VERTEX_POSITION_ATTRIBUTE_INDEX]); glBufferSubData(GL_ARRAY_BUFFER, 0, s_PositionArraySize, s_PositionArray); } // COLOR Update the vertex color if ( updateColor ) { glBindBuffer(GL_ARRAY_BUFFER, s_ArrayBufferIdArray[VERTEX_COLOR_ATTRIBUTE_INDEX]); glBufferSubData(GL_ARRAY_BUFFER, 0, s_ColorArraySize, s_ColorArray); } // NORMAL : Update vertex normals if ( updateNormal ) { glBindBuffer(GL_ARRAY_BUFFER, s_ArrayBufferIdArray[VERTEX_NORMAL_ATTRIBUTE_INDEX]); glBufferSubData(GL_ARRAY_BUFFER, 0, s_NormalArraySize, s_NormalArray); } // INDEX : Update vertex indices if ( updateIndex ) { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s_ElementArrayBufferId); glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, s_IndexArraySize, s_IndexArray); } DEMO_ASSERT_GL_ERROR(); } void Finalize(void) { FinalizeCube(); s_RenderSystem.Finalize(); s_AppHeap.Free(reinterpret_cast(s_AddrForGxHeap)); s_AppHeap.Finalize(); } void FinalizeCube(void) { DeallocateCube(); if ( s_ArrayBufferIdArray[0] != 0 ) { glDeleteBuffers(3, s_ArrayBufferIdArray); for (u32 index = 0; index < 3; index++) { s_ArrayBufferIdArray[index] = 0; } } if ( s_ElementArrayBufferId != 0 ) { glDeleteBuffers(1, &s_ElementArrayBufferId); s_ElementArrayBufferId = 0; } } void DeallocateCube(void) { if ( s_PositionArray != NULL ) { demo::Free((void*) s_PositionArray); s_PositionArray = NULL; } if ( s_ColorArray != NULL ) { demo::Free((void*) s_ColorArray); s_ColorArray = NULL; } if ( s_NormalArray != NULL ) { demo::Free((void*) s_NormalArray); s_NormalArray = NULL; } if ( s_IndexArray != NULL ) { demo::Free((void*) s_IndexArray); s_IndexArray = NULL; } } bool DrawFrame(void) { UpdateCamera(); DrawDisplay0(); DrawDisplay1(); s_RenderSystem.WaitVsync(NN_GX_DISPLAY_BOTH); // Stops executing the command list. nngxStopCmdlist(); return true; } void UpdateCamera(void) { nn::math::MTX34LookAt(&s_ViewMatrix, &s_CameraPosition, &s_CameraUp, &s_CameraTarget); } 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)); UpdateCube(); DrawCube(); 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); // 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); 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_Light0Ambient); glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE0_DIFFUSE], 1, s_Light0Diffuse); glUniform4fv(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_FRAGMENT_LIGHT_SOURCE0_POSITION], 1, s_Light0Position); // 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); // Fragment uniform : Texture combiner // Modulate fragment primary color and vertex color. glUniform3i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_SRC_RGB], GL_FRAGMENT_PRIMARY_COLOR_DMP, 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_MODULATE); glUniform1i(demo::s_UniformLocations[demo::FRAGMENT_UNIFORM_TEXENV2_COMBINE_ALPHA], GL_MODULATE); } void DrawDisplay1(void) { s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY1); s_RenderSystem.Clear(); s_RenderSystem.SwapBuffers(); } void UpdateCube(void) { static u32 mode = 1; static u32 counter = 0; static const u32 maxCounter = 120; s_Angle[1] += 1.0f; if ( s_Angle[1] > 360.f ) { s_Angle[1] -= 360.0f; } nn::math::Vector3 positionVector(s_Position[0], s_Position[1], s_Position[2]); nn::math::MTX34 positionMatrix; nn::math::MTX34Identity(&positionMatrix); nn::math::MTX34Translate(&positionMatrix, &positionVector); nn::math::MTX44 worldMatrix(positionMatrix); nn::math::MTX44 worldRotMatrix; nn::math::MTX44RotXYZDeg(&worldRotMatrix, s_Angle[0], s_Angle[1], s_Angle[2]); nn::math::MTX44Mult(&s_WorldMatrix, &worldMatrix, &worldRotMatrix); // Updates the vertex color periodically. if ( counter > maxCounter ) { if ( mode == 0 ) { SetCubeColor(1.0f, 0.0f, 0.0f, 1.0f); mode = 1; } else if ( mode == 1 ) { SetCubeColor(0.0f, 1.0f, 0.0f, 1.0f); mode = 2; } else if ( mode == 2 ) { SetCubeColor(0.0f, 0.0f, 1.0f, 1.0f); mode = 0; } // Updates the vertex buffer for vertex color UpdateCubeVBO(false, true, false, false); counter = 0; } else { counter++; } } void DrawCube(void) { nn::math::MTX44 modelViewMatrix(s_ViewMatrix); nn::math::MTX44Mult(&modelViewMatrix, &modelViewMatrix, &s_WorldMatrix); glUniformMatrix4fv(demo::s_UniformLocations[demo::VERTEX_UNIFORM_MODELVIEW], 1, GL_TRUE, static_cast(modelViewMatrix)); // POSITION glBindBuffer(GL_ARRAY_BUFFER, s_ArrayBufferIdArray[VERTEX_POSITION_ATTRIBUTE_INDEX]); glEnableVertexAttribArray(VERTEX_POSITION_ATTRIBUTE_INDEX); glVertexAttribPointer(VERTEX_POSITION_ATTRIBUTE_INDEX, VERTEX_POSITION_ATTRIBUTE_SIZE, GL_FLOAT, GL_FALSE, 0, 0); // COLOR glBindBuffer(GL_ARRAY_BUFFER, s_ArrayBufferIdArray[VERTEX_COLOR_ATTRIBUTE_INDEX]); glEnableVertexAttribArray(VERTEX_COLOR_ATTRIBUTE_INDEX); glVertexAttribPointer(VERTEX_COLOR_ATTRIBUTE_INDEX, VERTEX_COLOR_ATTRIBUTE_SIZE, GL_FLOAT, GL_FALSE, 0, 0); // NORMAL glBindBuffer(GL_ARRAY_BUFFER, s_ArrayBufferIdArray[VERTEX_NORMAL_ATTRIBUTE_INDEX]); glEnableVertexAttribArray(VERTEX_NORMAL_ATTRIBUTE_INDEX); glVertexAttribPointer(VERTEX_NORMAL_ATTRIBUTE_INDEX, VERTEX_NORMAL_ATTRIBUTE_SIZE, GL_FLOAT, GL_FALSE, 0, 0); for (u32 index = VERTEX_ATTRIBUTES_NUM; index < 8; index++) { glDisableVertexAttribArray(index); } glDrawElements(GL_TRIANGLES, s_TrianglesNum * 3, GL_UNSIGNED_SHORT, 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(); Initialize(); bool flag = true; while ( flag ) { flag = DrawFrame(); } Finalize(); }