/*---------------------------------------------------------------------------* Project: NintendoWare File: lyt_Common.cpp Copyright (C)2009-2010 Nintendo Co., Ltd./HAL Laboratory, Inc. 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. $Revision: 25594 $ *---------------------------------------------------------------------------*/ #include "precompiled.h" #include #include #include #include #include #include #include #include #define ARRAY_LENGTH(a) (sizeof(a) / sizeof((a)[0])) namespace nw { namespace lyt { // コンパイル時チェック void TevStage::CompileCheck() { NW_COMPILER_ASSERT( FIELD0_SIZE == BITS_SRCRGB * 3 + BITS_OPERANDRGB * 3 + BITS_COMBINERGB + BITS_SCALE + BITS_SAVEPREV); NW_COMPILER_ASSERT( FIELD1_SIZE == BITS_SRCALPHA * 3 + BITS_OPERANDALPHA * 3 + BITS_COMBINEALPHA + BITS_SCALE + BITS_SAVEPREV); NW_COMPILER_ASSERT( FIELD2_SIZE == BITS_KONSTSEL * 2); } namespace { #ifdef NW_LYT_DMPGL_ENABLED static const GLushort s_VertexIndex[] = { VERTEX_RT, VERTEX_LT, VERTEX_RB, VERTEX_LT, VERTEX_LB, VERTEX_RB, }; static const int s_NumVertex = ARRAY_LENGTH(s_VertexIndex); static const GLshort s_UniformVertexIndex[][VERTEXATTRSIZE_INDEX] = { { 0, 0 }, // LT { 1, 0 }, // RT { 0, 1 }, // LB { 1, 1 }, // RB }; NW_COMPILER_ASSERT(ARRAY_LENGTH(s_UniformVertexIndex) == VERTEX_MAX); static const GLfloat s_VertexPosition[][VERTEXATTRSIZE_POS] = { { 0.f, 0.f, 0.f, 1.f }, // LT { 1.f, 0.f, 0.f, 1.f }, // RT { 0.f, -1.f, 0.f, 1.f }, // LB { 1.f, -1.f, 0.f, 1.f }, // RB }; NW_COMPILER_ASSERT(ARRAY_LENGTH(s_VertexPosition) == VERTEX_MAX); #endif // NW_LYT_DMPGL_ENABLED } namespace internal { using namespace nw::math; bool EqualsResName(const char* name1, const char* name2) { return 0 == std::strncmp(name1, name2, ResourceNameStrMax); } bool EqualsMaterialName(const char* name1, const char* name2) { return 0 == std::strncmp(name1, name2, MaterialNameStrMax); } TexCoordAry::TexCoordAry() : m_Cap(0), m_Num(0), m_pData(NULL) { } void TexCoordAry::Free() { if (m_pData) { const u32 coordNum = m_Cap; Layout::DeleteArray(&m_pData[0][0], VERTEX_MAX * coordNum); m_pData = 0; m_Cap = 0; m_Num = 0; } } void TexCoordAry::Reserve(u8 num) { NW_ASSERT(num <= TexMapMax); if (m_Cap < num) { Free(); // テクスチャ座標 const u32 coordNum = num; math::VEC2 *const pVecAry = Layout::NewArray(VERTEX_MAX * coordNum); m_pData = reinterpret_cast(pVecAry); if (m_pData) { m_Cap = num; } } } void TexCoordAry::SetSize(u8 num) { if (m_pData && num <= m_Cap) { static const VEC2 texCoords[] = { VEC2(0.f, 0.f), VEC2(1.f, 0.f), VEC2(0.f, 1.f), VEC2(1.f, 1.f) }; NW_COMPILER_ASSERT(ARRAY_LENGTH(texCoords) == VERTEX_MAX); for (int j = m_Num; j < num; ++j) { for (int i = 0; i < VERTEX_MAX; ++i) { m_pData[j][i] = texCoords[i]; } } m_Num = num; } } void TexCoordAry::GetCoord( u32 idx, TexCoordQuad coord ) const { NW_ASSERT(idx < m_Num); for (int i = 0; i < VERTEX_MAX; ++i) { coord[i] = m_pData[idx][i]; } } void TexCoordAry::SetCoord( u32 idx, const TexCoordQuad coord ) { NW_ASSERT(idx < m_Num); for (int i = 0; i < VERTEX_MAX; ++i) { m_pData[idx][i] = coord[i]; } } void TexCoordAry::Copy( const void* pResTexCoord, u8 texCoordNum ) { NW_ASSERT(texCoordNum <= m_Cap); m_Num = ut::Max(m_Num, texCoordNum); const math::VEC2 (*src)[VERTEX_MAX] = static_cast(pResTexCoord); for (int j = 0; j < texCoordNum; ++j) { for (int i = 0; i < VERTEX_MAX; ++i) { m_pData[j][i] = src[j][i]; } } } const ut::Color8 MultipleAlpha( const ut::Color8 col, u8 alpha ) { ut::Color8 ret = col; if (alpha != ut::Color8::ALPHA_MAX) { ret.a = u8(col.a * alpha / ut::Color8::ALPHA_MAX); } return ret; } static f32 ColorU8ToFloat(u8 value) { return 1.0F / 255 * value; } #ifdef NW_LYT_DMPGL_ENABLED void DrawQuad( const DrawInfo& drawInfo, const VEC2& basePt, const Size& size, u8 texCoordNum, const VEC2 (*texCoords)[VERTEX_MAX], const ut::Color8* vtxColors ) { NW_LYT_STOPWATCH_MEASURE(-100, "nw::lyt::internal::DrawQuad"); GraphicsResource& gres = *drawInfo.GetGraphicsResource(); // プログラムが設定されてから一度だけ行う初期化。 gres.SetupProgram(); // 頂点カラー if (vtxColors != NULL) { GLint loc = gres.GetUniformLocation(gres.UNIFORM_uVertexColor); glUniform4f(loc + 0, vtxColors[0].r, vtxColors[0].g, vtxColors[0].b, vtxColors[0].a); glUniform4f(loc + 1, vtxColors[1].r, vtxColors[1].g, vtxColors[1].b, vtxColors[1].a); glUniform4f(loc + 2, vtxColors[2].r, vtxColors[2].g, vtxColors[2].b, vtxColors[2].a); glUniform4f(loc + 3, vtxColors[3].r, vtxColors[3].g, vtxColors[3].b, vtxColors[3].a); NW_GL_ASSERT(); } // テクスチャ座標 if (texCoordNum > 0 && texCoords != NULL) { for (int i = 0; i < TexMapMax; ++i) { int src = gres.GetTexCoordSrc(i); if (0 <= src && texCoords != NULL && src < texCoordNum) { GLint loc = gres.GetUniformLocation(gres.UNIFORM_uVertexTexCoord0 + i); glUniform4f(loc + 0, texCoords[src][0].x, texCoords[src][0].y, 0.0f, 1.0f); glUniform4f(loc + 1, texCoords[src][1].x, texCoords[src][1].y, 0.0f, 1.0f); glUniform4f(loc + 2, texCoords[src][2].x, texCoords[src][2].y, 0.0f, 1.0f); glUniform4f(loc + 3, texCoords[src][3].x, texCoords[src][3].y, 0.0f, 1.0f); NW_GL_ASSERT(); } } } // ローカル座標変換を設定 { GLint loc = gres.GetUniformLocation(gres.UNIFORM_uTransform); glUniform4f(loc, size.width, size.height, basePt.x, basePt.y); NW_GL_ASSERT(); } gres.LoadMtxModelView(); NW_GL_ASSERT(); glDrawElements(GL_TRIANGLES, s_NumVertex, GL_UNSIGNED_SHORT, 0); NW_GL_ASSERT(); } // @brief 前回と同じ設定で描画を繰り返す void DrawQuad_Repeat( const DrawInfo& drawInfo, const VEC2& basePt, const Size& size ) { NW_LYT_STOPWATCH_MEASURE(-101, "nw::lyt::internal::DrawQuad_Repeat"); GraphicsResource& gres = *drawInfo.GetGraphicsResource(); // ローカル座標変換を設定 { GLint loc = gres.GetUniformLocation(gres.UNIFORM_uTransform); glUniform4f(loc, size.width, size.height, basePt.x, basePt.y); NW_GL_ASSERT(); } glDrawElements(GL_TRIANGLES, s_NumVertex, GL_UNSIGNED_SHORT, 0); NW_GL_ASSERT(); } void DrawLine( const DrawInfo& drawInfo, const math::VEC2& pos, const Size& size, ut::Color8 color) { GraphicsResource& graphicsResource = *drawInfo.GetGraphicsResource(); GLuint program = graphicsResource.GetGlProgramDebug(); graphicsResource.UseProgram(program); // バッファオブジェクトは使わない。 glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); // 頂点座標 glEnableVertexAttribArray(VERTEXATTR_POS); glVertexAttribPointer(VERTEXATTR_POS, VERTEXATTRSIZE_POS, GL_FLOAT, GL_FALSE, 0, s_VertexPosition); glDisableVertexAttribArray(VERTEXATTR_COLOR); glDisableVertexAttribArray(VERTEXATTR_TEXCOORD0); glDisableVertexAttribArray(VERTEXATTR_TEXCOORD1); glDisableVertexAttribArray(VERTEXATTR_TEXCOORD2); glDisable(GL_BLEND); glDisable(GL_COLOR_LOGIC_OP); NW_GL_ASSERT(); glUniform4f(glGetUniformLocation(program, "dmp_TexEnv[0].constRgba"), ColorU8ToFloat(color.r), ColorU8ToFloat(color.g), ColorU8ToFloat(color.b), ColorU8ToFloat(color.a)); NW_GL_ASSERT(); f32 x = pos.x; f32 y = pos.y; f32 w = size.width; f32 h = size.height; f32 u = ((w > 0.f)? 1.f : -1.f) * 2.f; f32 v = ((h > 0.f)? 1.f : -1.f) * 2.f; // LINEが描けないので、4つの矩形で表現する。 { nw::math::MTX44 m( w, 0, 0, x, 0, v, 0, y, 0, 0, 1, 0, 0, 0, 0, 1); internal::MTX44Mult(&m, &graphicsResource.GetMtxModelView(), &m); glUniformMatrix4fv(glGetUniformLocation(program, "uModelView"), 1, GL_TRUE, m.a); NW_GL_ASSERT(); glDrawElements(GL_TRIANGLES, s_NumVertex, GL_UNSIGNED_SHORT, s_VertexIndex); NW_GL_ASSERT(); } { nw::math::MTX44 m( w, 0, 0, x, 0, v, 0, y - h, 0, 0, 1, 0, 0, 0, 0, 1); internal::MTX44Mult(&m, &graphicsResource.GetMtxModelView(), &m); glUniformMatrix4fv(glGetUniformLocation(program, "uModelView"), 1, GL_TRUE, m.a); NW_GL_ASSERT(); glDrawElements(GL_TRIANGLES, s_NumVertex, GL_UNSIGNED_SHORT, s_VertexIndex); NW_GL_ASSERT(); } { nw::math::MTX44 m( u, 0, 0, x, 0, h, 0, y, 0, 0, 1, 0, 0, 0, 0, 1); internal::MTX44Mult(&m, &graphicsResource.GetMtxModelView(), &m); glUniformMatrix4fv(glGetUniformLocation(program, "uModelView"), 1, GL_TRUE, m.a); NW_GL_ASSERT(); glDrawElements(GL_TRIANGLES, s_NumVertex, GL_UNSIGNED_SHORT, s_VertexIndex); NW_GL_ASSERT(); } { nw::math::MTX44 m( u, 0, 0, x + w, 0, h, 0, y, 0, 0, 1, 0, 0, 0, 0, 1); internal::MTX44Mult(&m, &graphicsResource.GetMtxModelView(), &m); glUniformMatrix4fv(glGetUniformLocation(program, "uModelView"), 1, GL_TRUE, m.a); NW_GL_ASSERT(); glDrawElements(GL_TRIANGLES, s_NumVertex, GL_UNSIGNED_SHORT, s_VertexIndex); NW_GL_ASSERT(); } NW_GL_ASSERT(); } // 外部のシェーダに影響を与えないように後始末。 void FinalizeGraphics() { glDisableVertexAttribArray(VERTEXATTR_POS); glDisableVertexAttribArray(VERTEXATTR_COLOR); glDisableVertexAttribArray(VERTEXATTR_TEXCOORD0); glDisableVertexAttribArray(VERTEXATTR_TEXCOORD1); glDisableVertexAttribArray(VERTEXATTR_TEXCOORD2); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); } void GL::SetTextureSamplerType(GraphicsResource& graphicsResource, int index, int value) { //NW_MINMAX_ASSERT(index, 0, internal::TexUnitMax - 1); GLint loc = graphicsResource.GetUniformLocation(graphicsResource.UNIFORM_dmp_Texture0_samplerType + index); glUniform1i(loc, value); } static const int tevMode[] = { GL_REPLACE, GL_MODULATE, GL_ADD, GL_ADD_SIGNED, GL_INTERPOLATE, GL_SUBTRACT, GL_ADD_MULT_DMP, GL_MULT_ADD_DMP, }; NW_COMPILER_ASSERT(ARRAY_LENGTH(tevMode) == TEVMODE_MAX); void GL::SetTevCombineRgb(GraphicsResource& graphicsResource, int index, TevMode value) { //NW_MINMAX_ASSERT(index, 0, internal::TexEnvUnitMax - 1); GLint loc = graphicsResource.GetUniformLocation(graphicsResource.UNIFORM_dmp_TexEnv0_combineRgb + index); glUniform1i(loc, tevMode[value]); } void GL::SetTevCombineAlpha(GraphicsResource& graphicsResource, int index, TevMode value) { //NW_MINMAX_ASSERT(index, 0, internal::TexEnvUnitMax - 1); GLint loc = graphicsResource.GetUniformLocation(graphicsResource.UNIFORM_dmp_TexEnv0_combineAlpha + index); glUniform1i(loc, tevMode[value]); } static const int tevSrc[] = { GL_TEXTURE0, GL_TEXTURE1, GL_TEXTURE2, GL_TEXTURE3, GL_CONSTANT, GL_PRIMARY_COLOR, GL_PREVIOUS, #ifdef NW_TARGET_CTR_GL_FINAL GL_PREVIOUS_BUFFER_DMP, #else GL_CONSTANT, #endif }; NW_COMPILER_ASSERT(ARRAY_LENGTH(tevSrc) == TEVSRC_MAX); void GL::SetTevSrcRgb(GraphicsResource& graphicsResource, int index, TevSrc value0, TevSrc value1, TevSrc value2) { //NW_MINMAX_ASSERT(index, 0, internal::TexEnvUnitMax - 1); GLint ivec[3] = { tevSrc[value0], tevSrc[value1], tevSrc[value2] }; GLint loc = graphicsResource.GetUniformLocation(graphicsResource.UNIFORM_dmp_TexEnv0_srcRgb + index); glUniform3iv(loc, 1, ivec); } void GL::SetTevSrcAlpha(GraphicsResource& graphicsResource, int index, TevSrc value0, TevSrc value1, TevSrc value2) { //NW_MINMAX_ASSERT(index, 0, internal::TexEnvUnitMax - 1); GLint ivec[3] = { tevSrc[value0], tevSrc[value1], tevSrc[value2] }; GLint loc = graphicsResource.GetUniformLocation(graphicsResource.UNIFORM_dmp_TexEnv0_srcAlpha + index); glUniform3iv(loc, 1, ivec); } void GL::SetTevOperandRgb(GraphicsResource& graphicsResource, int index, TevOpRgb value0, TevOpRgb value1, TevOpRgb value2) { static const int tevOpRgb[] = { GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, #ifdef NW_TARGET_CTR_GL_FINAL GL_SRC_R_DMP, GL_ONE_MINUS_SRC_R_DMP, GL_SRC_G_DMP, GL_ONE_MINUS_SRC_G_DMP, GL_SRC_B_DMP, GL_ONE_MINUS_SRC_B_DMP, #else GL_SRC_COLOR, // RRR GL_ONE_MINUS_SRC_COLOR, // INV_RRR GL_SRC_COLOR, // GGG GL_ONE_MINUS_SRC_COLOR, // INV_GGG GL_SRC_COLOR, // BBB GL_ONE_MINUS_SRC_COLOR, // INV_BBB #endif }; NW_COMPILER_ASSERT(ARRAY_LENGTH(tevOpRgb) == TEVOPRGB_MAX); //NW_MINMAX_ASSERT(index, 0, internal::TexEnvUnitMax - 1); GLint ivec[3] = { tevOpRgb[value0], tevOpRgb[value1], tevOpRgb[value2] }; GLint loc = graphicsResource.GetUniformLocation(graphicsResource.UNIFORM_dmp_TexEnv0_operandRgb + index); glUniform3iv(loc, 1, ivec); } void GL::SetTevOperandAlpha(GraphicsResource& graphicsResource, int index, TevOpAlp value0, TevOpAlp value1, TevOpAlp value2) { static const int tevOpAlp[] = { GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, #ifdef NW_TARGET_CTR_GL_FINAL GL_SRC_R_DMP, GL_ONE_MINUS_SRC_R_DMP, GL_SRC_G_DMP, GL_ONE_MINUS_SRC_G_DMP, GL_SRC_B_DMP, GL_ONE_MINUS_SRC_B_DMP, #else GL_SRC_ALPHA, // R GL_ONE_MINUS_SRC_ALPHA, // INV_R GL_SRC_ALPHA, // G GL_ONE_MINUS_SRC_ALPHA, // INV_G GL_SRC_ALPHA, // B GL_ONE_MINUS_SRC_ALPHA, // INV_B #endif }; NW_COMPILER_ASSERT(ARRAY_LENGTH(tevOpAlp) == TEVOPALP_MAX); //NW_MINMAX_ASSERT(index, 0, internal::TexEnvUnitMax - 1); GLint ivec[3] = { tevOpAlp[value0], tevOpAlp[value1], tevOpAlp[value2] }; GLint loc = graphicsResource.GetUniformLocation(graphicsResource.UNIFORM_dmp_TexEnv0_operandAlpha + index); glUniform3iv(loc, 1, ivec); } static const float scale[] = { 1.0F, 2.0F, 4.0F, }; NW_COMPILER_ASSERT(ARRAY_LENGTH(scale) == TEVSCALE_MAX); void GL::SetTevScaleRgb(GraphicsResource& graphicsResource, int index, TevScale value) { //NW_MINMAX_ASSERT(index, 0, internal::TexEnvUnitMax - 1); GLint loc = graphicsResource.GetUniformLocation(graphicsResource.UNIFORM_dmp_TexEnv0_scaleRgb + index); glUniform1f(loc, scale[value]); } void GL::SetTevScaleAlpha(GraphicsResource& graphicsResource, int index, TevScale value) { //NW_MINMAX_ASSERT(index, 0, internal::TexEnvUnitMax - 1); GLint loc = graphicsResource.GetUniformLocation(graphicsResource.UNIFORM_dmp_TexEnv0_scaleAlpha + index); glUniform1f(loc, scale[value]); } void GL::SetTevConstRgba(GraphicsResource& graphicsResource, int index, nw::ut::Color8 value) { GLfloat fvec[4] = { ColorU8ToFloat(value.r), ColorU8ToFloat(value.g), ColorU8ToFloat(value.b), ColorU8ToFloat(value.a), }; GLint loc = graphicsResource.GetUniformLocation(graphicsResource.UNIFORM_dmp_TexEnv0_constRgba + index); glUniform4fv(loc, 1, fvec); } void GL::SetTevConstRgba(GraphicsResource& graphicsResource, int index, nw::ut::Color8 value0, nw::ut::Color8 value1) { GLfloat fvec[4] = { ColorU8ToFloat(value0.r), ColorU8ToFloat(value0.g), ColorU8ToFloat(value0.b), ColorU8ToFloat(value1.a), }; GLint loc = graphicsResource.GetUniformLocation(graphicsResource.UNIFORM_dmp_TexEnv0_constRgba + index); glUniform4fv(loc, 1, fvec); } void GL::SetTevBufferColor(nw::lyt::GraphicsResource &graphicsResource, ut::Color8 value) { #ifdef NW_TARGET_CTR_GL_FINAL GLint loc = graphicsResource.GetUniformLocation(graphicsResource.UNIFORM_dmp_TexEnv0_bufferColor); glUniform4f( loc, ColorU8ToFloat(value.r), ColorU8ToFloat(value.g), ColorU8ToFloat(value.b), ColorU8ToFloat(value.a)); #else NW_UNUSED_VARIABLE(graphicsResource) NW_UNUSED_VARIABLE(value) #endif } void GL::SetTevBufferInput(nw::lyt::GraphicsResource &graphicsResource, int index, bool valueRgb, bool valueAlpha) { #ifdef NW_TARGET_CTR_GL_FINAL //NW_MINMAX_ASSERT(index, 1, 4); GLint loc = graphicsResource.GetUniformLocation(graphicsResource.UNIFORM_dmp_TexEnv1_bufferInput + index - 1); glUniform2i( loc, valueRgb? GL_PREVIOUS : GL_PREVIOUS_BUFFER_DMP, valueAlpha? GL_PREVIOUS : GL_PREVIOUS_BUFFER_DMP); #else NW_UNUSED_VARIABLE(graphicsResource) NW_UNUSED_VARIABLE(index) NW_UNUSED_VARIABLE(valueRgb) NW_UNUSED_VARIABLE(valueAlpha) #endif } void GL::SetEnableAlphaTest(nw::lyt::GraphicsResource &graphicsResource, bool value) { GLint loc = graphicsResource.GetUniformLocation(graphicsResource.UNIFORM_dmp_FragOperation_enableAlphaTest); glUniform1i(loc, value? GL_TRUE : GL_FALSE); } void GL::SetAlphaRefValue(nw::lyt::GraphicsResource &graphicsResource, f32 value) { GLint loc = graphicsResource.GetUniformLocation(graphicsResource.UNIFORM_dmp_FragOperation_alphaRefValue); glUniform1f(loc, value); } void GL::SetAlphaTestFunc(nw::lyt::GraphicsResource &graphicsResource, nw::lyt::AlphaTest value) { static const GLint alphaTest[] = { GL_NEVER, GL_LESS, GL_LEQUAL, GL_EQUAL, GL_NOTEQUAL, GL_GEQUAL, GL_GREATER, GL_ALWAYS, }; NW_COMPILER_ASSERT(ARRAY_LENGTH(alphaTest) == ALPHATEST_MAX); GLint loc = graphicsResource.GetUniformLocation(graphicsResource.UNIFORM_dmp_FragOperation_alphaTestFunc); glUniform1i(loc, alphaTest[value]); } static const GLint filterMode[] = { GL_NEAREST, GL_LINEAR, }; NW_COMPILER_ASSERT(ARRAY_LENGTH(filterMode) == TEXFILTER_MAX); void GL::SetTexMinFilter(nw::lyt::GraphicsResource&, nw::lyt::TexFilter value) { //NW_MINMAX_ASSERT(value, 0, TEXFILTER_MAX - 1); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filterMode[value]); } void GL::SetTexMagFilter(nw::lyt::GraphicsResource&, nw::lyt::TexFilter value) { //NW_MINMAX_ASSERT(value, 0, TEXFILTER_MAX - 1); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filterMode[value]); } #endif // NW_LYT_DMPGL_ENABLED } // namespace nw::lyt::internal #ifdef NW_LYT_DMPGL_ENABLED void GraphicsResource::InitVBO() { glGenBuffers(this->VBO_MAX, m_GlVertexBufferObject); NW_GL_ASSERT(); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->GetVBO(this->VBO_ELEMENT)); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(s_VertexIndex), s_VertexIndex, GL_STATIC_DRAW); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); NW_GL_ASSERT(); glBindBuffer(GL_ARRAY_BUFFER, this->GetVBO(this->VBO_VERTEX_INDEX)); glBufferData(GL_ARRAY_BUFFER, sizeof(s_UniformVertexIndex), s_UniformVertexIndex, GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); NW_GL_ASSERT(); } #endif } // namespace nw::lyt } // namespace nw