示例#1
0
文件: Shader.cpp 项目: BSkin/MTG
Shader * Shader::loadShader(string name)
{
	Shader * s = new Shader();
	
	for (int i = 0; i < 5; i++) name.pop_back();
	s->name = name;

	string vertPath = name + ".vert";
	string fragPath = name + ".frag";

	//Start with a handle for the shader program...
	GLhandleARB shaderProgramHandle = glCreateProgramObjectARB ();

	//glBindAttribLocation (shaderProgramHandle, 0, "mg_vertex");
	//glBindAttribLocation (shaderProgramHandle, 1, "uv");
	// use glGetAttribLocation  instead

	GLhandleARB vertObject = makeShader(vertPath.c_str(), GL_VERTEX_SHADER);
	GLhandleARB fragObject = makeShader(fragPath.c_str(), GL_FRAGMENT_SHADER);
	glAttachObjectARB(shaderProgramHandle, vertObject);
	glAttachObjectARB(shaderProgramHandle, fragObject);

	glLinkProgramARB (shaderProgramHandle);
	
	//Find out if compilation worked and return the program handle if it did...
	int status; glGetObjectParameterivARB (shaderProgramHandle, GL_OBJECT_LINK_STATUS_ARB, &status);
	if (status != 0) 
	{
		//return shaderProgramHandle; //Everything OK...
		s->shaderProgram = shaderProgramHandle;
		s->vertexShader = vertObject;
		s->fragmentShader = fragObject;

		return s;
	}

	//It didn't, so log error information...
	//::log ("\nFailed to link shader \"%s\"...", name.c_str ());
	int length = 0; 
	glGetObjectParameterivARB (shaderProgramHandle, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
	glBindFragDataLocation(shaderProgramHandle, 0, "outColour");

	const long MAXIMUM_LOG_STRING = 1024; char logString [MAXIMUM_LOG_STRING];
	GLsizei messageLength = min (length, MAXIMUM_LOG_STRING);
	if (messageLength > 0) {
		glGetInfoLogARB (shaderProgramHandle, messageLength, 0, logString);
	}

	//and detach what was previously attached and discard the program handle that was obtained...
	glDetachObjectARB(shaderProgramHandle, fragObject);
	glDetachObjectARB(shaderProgramHandle, vertObject);

	glDeleteObjectARB (shaderProgramHandle); //Should also detach the attached handles...

	return NULL;
}
示例#2
0
	ShaderManager::ShaderProgram* ShaderManager::makeShaderProgram(const char* programName, const char* vertexShaderFile, const char* fragmentShaderFile){
		//Create the shaders with filename as name
		Shader* vsShader = makeShader(vertexShaderFile, Vertex, vertexShaderFile);
		Shader* fsShader = makeShader(fragmentShaderFile, Fragment, fragmentShaderFile);
		
		if( vsShader == 0 || fsShader == 0 ) return 0;
		
		ShaderProgram* newProgram = new ShaderProgram();
		shaderPrograms.insert(ShaderProgramContainer::value_type(programName, newProgram));
		newProgram->attachShader(vsShader);
		newProgram->attachShader(fsShader);
        
        return newProgram;
	}
示例#3
0
static int initShaders(void){
    vertex_shader = makeShader( GL_VERTEX_SHADER, "noop.v.glsl");
    if (vertex_shader == 0)
        return 0;

    fragment_shader = makeShader( GL_FRAGMENT_SHADER, "noop.f.glsl");
    if (fragment_shader == 0)
        return 0;

    program = makeProgram(vertex_shader, fragment_shader);
    if (program == 0)
        return 0;

    glUseProgram(program);
}
示例#4
0
static void draw_gradients(SkCanvas* canvas,
                           sk_sp<SkShader> (*makeShader)(const SkPoint[2], const SkMatrix&),
                           const SkPoint ptsArray[][2], int numImages) {
    // Use some nice prime numbers for the rectangle and matrix with
    // different scaling along the x and y axes (which is the bug this
    // test addresses, where incorrect order of operations mixed up the axes)
    SkRect rectGrad = {
        SkIntToScalar(43),  SkIntToScalar(61),
        SkIntToScalar(181), SkIntToScalar(167) };
    SkMatrix shaderMat;
    shaderMat.setScale(rectGrad.width(), rectGrad.height());
    shaderMat.postTranslate(rectGrad.left(), rectGrad.top());

    canvas->save();
    for (int i = 0; i < numImages; i++) {
        // Advance line downwards if necessary.
        if (i % IMAGES_X == 0 && i != 0) {
            canvas->restore();
            canvas->translate(0, TESTGRID_Y);
            canvas->save();
        }

        SkPaint paint;
        paint.setShader(makeShader(*ptsArray, shaderMat));
        canvas->drawRect(rectGrad, paint);

        // Advance to next position.
        canvas->translate(TESTGRID_X, 0);
        ptsArray++;
    }
    canvas->restore();
}
示例#5
0
DEF_TEST(serial_procs_picture, reporter) {

    auto p1 = make_pic([](SkCanvas* c) {
        // need to be large enough that drawPictures doesn't "unroll" us
        for (int i = 0; i < 20; ++i) {
            c->drawColor(SK_ColorRED);
        }
    });

    // now use custom serialization
    auto p0 = make_pic([](SkCanvas* c) { c->drawColor(SK_ColorBLUE); });
    test_pictures(reporter, p0, 1, false);

    // test inside effect
    p0 = make_pic([p1](SkCanvas* c) {
        SkPaint paint;
        SkTileMode tm = SkTileMode::kClamp;
        paint.setShader(p1->makeShader(tm, tm));
        c->drawPaint(paint);
    });
    test_pictures(reporter, p0, 1, true);

    // test nested picture
    p0 = make_pic([p1](SkCanvas* c) {
        c->drawColor(SK_ColorRED);
        c->drawPicture(p1);
        c->drawColor(SK_ColorBLUE);
    });
    test_pictures(reporter, p0, 1, true);
}
示例#6
0
//-----------------------------------------------------------------------------
// compil
//-----------------------------------------------------------------------------
int Shader::compil( const char *vertex, const char *fragment )
{
    m_program = glCreateProgramObjectARB();
	if( !makeShader(vertex, GL_VERTEX_SHADER_ARB) )
    {
        //QMessageBox::critical(NULL, "Error", "Can't compil the vertex shader !");
		return SHADER_VERTEX_ERROR;
    }
    if( !makeShader(fragment, GL_FRAGMENT_SHADER_ARB) )
    {
        //QMessageBox::critical(NULL, "Error", "Can't compil this pixel shader !");
        return SHADER_FRAGMENT_ERROR;
    }

    glLinkProgram(m_program);

	return SHADER_SUCCESS;
}
示例#7
0
int main(int argc, char **argv) {
	EnumGenerator::generate2();
//	qDebug() << Enum::__ENUM_CLASS::Item0.name();
//	qDebug() << ListEnum::Item0.id() << ListEnum::Item0.toString();
//	Test t = Test::v1;
//	Test::v1.key();
	QCoreApplication app(argc, argv);
	makeShader();
//	EnumGenerator::generate();
	return 0;
}
示例#8
0
    GLuint compile_shaders(void)
    {
        GLuint program;

		int result = 0;

        program = glCreateProgram();

        makeShader(GL_VERTEX_SHADER, "Shaders/VertexShader.vert", program);
        //makeShader(GL_TESS_CONTROL_SHADER, "TessControlShader.glsl", program);
        //makeShader(GL_TESS_EVALUATION_SHADER, "TessEvalShader.glsl", program);
        //makeShader(GL_GEOMETRY_SHADER, "GeomShader.glsl", program);
        makeShader(GL_FRAGMENT_SHADER, "Shaders/FragmentShader.frag", program);

        glLinkProgram(program);
        
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
		glPointSize(5.0f);
        return program;
    }
示例#9
0
文件: main.cpp 项目: JamesLinus/hifi
    QTestWindow() {
        setSurfaceType(QSurface::OpenGLSurface);

        QSurfaceFormat format;
        // Qt Quick may need a depth and stencil buffer. Always make sure these are available.
        format.setDepthBufferSize(16);
        format.setStencilBufferSize(8);
        format.setVersion(4, 3);
        format.setProfile(QSurfaceFormat::OpenGLContextProfile::CoreProfile);
        format.setOption(QSurfaceFormat::DebugContext);
        format.setSwapInterval(0);

        setFormat(format);

        _qGlContext.setFormat(format);
        _qGlContext.create();

        show();
        makeCurrent();
        setupDebugLogger(this);

        gpu::Context::init<gpu::GLBackend>();
        _context = std::make_shared<gpu::Context>();
        
        auto shader = makeShader(unlit_vert, unlit_frag, gpu::Shader::BindingSet{});
        auto state = std::make_shared<gpu::State>();
        state->setMultisampleEnable(true);
        state->setDepthTest(gpu::State::DepthTest { true });
        _pipeline = gpu::Pipeline::create(shader, state);
        
        // Clear screen
        gpu::Batch batch;
        batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLORS, { 1.0, 0.0, 0.5, 1.0 });
        _context->render(batch);
        
        DependencyManager::set<GeometryCache>();
        DependencyManager::set<DeferredLightingEffect>();

        resize(QSize(800, 600));
        
        _time.start();
    }
示例#10
0
void PtexViewer::render(int selx, int sely)
{
    if (!_shaderProgram) makeShader();

    if (_options.bgColorLight) glClearColor(0.8,0.8,0.8,1);
    else glClearColor(0.0,0.0,0.0,1);
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
    
    GLint vp[4];  
    glGetIntegerv(GL_VIEWPORT, vp);
    float width = vp[2];
    float height = vp[3];
    float winasp = width/height;
    
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    bool selectMode = selx>=0 && sely>=0;
    
    if (selectMode)
        gluPickMatrix((double)selx,(double)vp[3]-sely,3,3,vp);
    
    if (!_mode3d||_displayFace>=0)
    {
        float sc = _cam.getDistance()/2;
        glOrtho(-sc, sc, -sc/winasp, sc/winasp, -100, 100);

        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        glTranslatef(-_cam.getLookAt()[0],-_cam.getLookAt()[1],-_cam.getLookAt()[2]);
    }
    else
    {
        _cam.applyProjectionTransform(winasp, _bounds);

        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        _cam.applyModelViewTransform();
    }
    
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_POLYGON_OFFSET_FILL);
    glPolygonOffset(1.0,1.0);
    glColor4f(1.0, 1.0, 1.0, 1.0);
    glUseProgramObjectARB(_shaderProgram);
    _geometry.draw(_displayFace);
    glUseProgramObjectARB(0);
    if (!selectMode && _options.showGridLines)
    {
        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        glEnable(GL_LINE_SMOOTH);
        glColor4f(0.0, 0.0, 0.0, 0.25);
        _geometry.draw(_displayFace);
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
        glDisable(GL_BLEND);
        glDisable(GL_LINE_SMOOTH);
    }
    glDisable(GL_POLYGON_OFFSET_FILL);
    glDisable(GL_DEPTH_TEST);
    
    if (selectMode) return;
    
    // Display text information
    char str[64];
    
    if (_options.bgColorLight) glColor3f(0.0, 0.0, 0.0);
    else glColor3f(0.9, 0.9, 0.9);
    
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    
    if (!_options.envMode)
    {
        if (_numFaces==1) strcpy(str, "1 face");
        else sprintf(str,"%i faces",_numFaces);

        renderChars(-0.8,-0.92,GLUT_BITMAP_8_BY_13,str);
        if (_displayFace>=0 && _numFaces!=1)
        {
            sprintf(str,"Face ID: %i",_displayFace);
            renderChars(-0.8,0.92,GLUT_BITMAP_8_BY_13,str);
        }
        if (_numFaces==1)
        {
            int ures = _geometry.getFace(0)->ures;
            int vres = _geometry.getFace(0)->vres;
            sprintf(str,"Res: %i x %i",ures,vres);
            renderChars(-0.8,0.92,GLUT_BITMAP_8_BY_13,str);
        }
        else if (_displayFace>=0)
        {
            int ures = _geometry.getFace(_displayFace)->ures;
            int vres = _geometry.getFace(_displayFace)->vres;
            sprintf(str,"Face Res: %i x %i",ures,vres);
            renderChars(-0.2,0.92,GLUT_BITMAP_8_BY_13,str);
        }
        renderChars(0.25,-0.92,GLUT_BITMAP_8_BY_13,(char*)_typeStr.c_str());
    }
}
示例#11
0
void DisplayOzone::drawWithTexture(Buffer *buffer)
{
    FunctionsGL *gl    = mFunctionsGL;
    StateManagerGL *sm = getRenderer()->getStateManager();

    if (!mProgram)
    {
        const GLchar *vertexSource =
            "#version 100\n"
            "attribute vec3 vertex;\n"
            "uniform vec2 center;\n"
            "uniform vec2 windowSize;\n"
            "uniform vec2 borderSize;\n"
            "uniform float depth;\n"
            "varying vec3 texCoord;\n"
            "void main()\n"
            "{\n"
            "    vec2 pos = vertex.xy * (windowSize + borderSize * vertex.z);\n"
            "    gl_Position = vec4(center + pos, depth, 1);\n"
            "    texCoord = vec3(pos / windowSize * vec2(.5, -.5) + vec2(.5, .5), vertex.z);\n"
            "}\n";

        const GLchar *fragmentSource =
            "#version 100\n"
            "precision mediump float;\n"
            "uniform sampler2D tex;\n"
            "varying vec3 texCoord;\n"
            "void main()\n"
            "{\n"
            "    if (texCoord.z > 0.)\n"
            "    {\n"
            "        float c = abs((texCoord.z * 2.) - 1.);\n"
            "        gl_FragColor = vec4(c, c, c, 1);\n"
            "    }\n"
            "    else\n"
            "    {\n"
            "        gl_FragColor = texture2D(tex, texCoord.xy);\n"
            "    }\n"
            "}\n";

        mVertexShader   = makeShader(GL_VERTEX_SHADER, vertexSource);
        mFragmentShader = makeShader(GL_FRAGMENT_SHADER, fragmentSource);
        mProgram = gl->createProgram();
        gl->attachShader(mProgram, mVertexShader);
        gl->attachShader(mProgram, mFragmentShader);
        gl->bindAttribLocation(mProgram, 0, "vertex");
        gl->linkProgram(mProgram);
        GLint linked;
        gl->getProgramiv(mProgram, GL_LINK_STATUS, &linked);
        ASSERT(linked);
        mCenterUniform     = gl->getUniformLocation(mProgram, "center");
        mWindowSizeUniform = gl->getUniformLocation(mProgram, "windowSize");
        mBorderSizeUniform = gl->getUniformLocation(mProgram, "borderSize");
        mDepthUniform      = gl->getUniformLocation(mProgram, "depth");
        GLint texUniform = gl->getUniformLocation(mProgram, "tex");
        sm->useProgram(mProgram);
        gl->uniform1i(texUniform, 0);

        // clang-format off
        const GLfloat vertices[] =
        {
             // window corners, and window border inside corners
             1, -1, 0,
            -1, -1, 0,
             1,  1, 0,
            -1,  1, 0,
             // window border outside corners
             1, -1, 1,
            -1, -1, 1,
             1,  1, 1,
            -1,  1, 1,
        };
        // clang-format on
        gl->genBuffers(1, &mVertexBuffer);
        sm->bindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
        gl->bufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

        // window border triangle strip
        const GLuint borderStrip[] = {5, 0, 4, 2, 6, 3, 7, 1, 5, 0};

        gl->genBuffers(1, &mIndexBuffer);
        sm->bindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
        gl->bufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(borderStrip), borderStrip, GL_STATIC_DRAW);
    }
    else
    {
        sm->useProgram(mProgram);
        sm->bindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
        sm->bindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
    }

    // convert from pixels to "-1 to 1" space
    const NativeWindow *n = buffer->getNative();
    double x              = n->x * 2. / mWidth - 1;
    double y              = n->y * 2. / mHeight - 1;
    double halfw          = n->width * 1. / mWidth;
    double halfh          = n->height * 1. / mHeight;
    double borderw        = n->borderWidth * 2. / mWidth;
    double borderh        = n->borderHeight * 2. / mHeight;

    gl->uniform2f(mCenterUniform, x + halfw, y + halfh);
    gl->uniform2f(mWindowSizeUniform, halfw, halfh);
    gl->uniform2f(mBorderSizeUniform, borderw, borderh);
    gl->uniform1f(mDepthUniform, n->depth / 1e6);

    sm->setBlendEnabled(false);
    sm->setCullFaceEnabled(false);
    sm->setStencilTestEnabled(false);
    sm->setScissorTestEnabled(false);
    sm->setDepthTestEnabled(true);
    sm->setColorMask(true, true, true, true);
    sm->setDepthMask(true);
    sm->setDepthRange(0, 1);
    sm->setDepthFunc(GL_LESS);
    sm->setViewport(gl::Rectangle(0, 0, mWidth, mHeight));
    sm->activeTexture(0);
    GLuint tex = buffer->getTexture();
    sm->bindTexture(GL_TEXTURE_2D, tex);
    gl->vertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
    gl->enableVertexAttribArray(0);
    sm->bindFramebuffer(GL_DRAW_FRAMEBUFFER, mDrawing->getGLFB());
    gl->drawArrays(GL_TRIANGLE_STRIP, 0, 4);
    gl->drawElements(GL_TRIANGLE_STRIP, 10, GL_UNSIGNED_INT, 0);
    sm->deleteTexture(tex);
}
示例#12
0
void SetupRC()
{
    
    SpriteManager *sprites = SpriteManager::instance();
    
    Vector p(0.0f,0.0f,-1.0f);
    player = new Player("resources/Models/cube.ogl", p);
    
    sprites->AddSprite( player);
    
    std::string filename="resources/Models/cube.ogl";
    test = new Model(filename);
    
    /*
    Vector v((GLfloat)(0), (GLfloat)(0), (GLfloat) (5) );
    sprites->AddSprite( new Sprite("resources/Models/cube.ogl", v) );
    */
    for (int i=0; i<30; i++) {
        
        Vector v((GLfloat)(0), (GLfloat)(i *3 ), (GLfloat) (10) );
        
        sprites->AddSprite(  new Sprite("resources/Models/cube.ogl", v, i*8, i*2, i*5) );
        
    }
    
	glEnable(GL_DEPTH_TEST);
	glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
	
	glClearColor(0.0f, 0.0f, 0.0f, 1.0f );
    
    shader.vertexShader = makeShader( GL_VERTEX_SHADER, "resources/Shaders/identity.vs");
    if(shader.vertexShader == 0){
        printf("failed to make vertex shader");
        exit(0);
    }
    
    shader.fragmentShader = makeShader(GL_FRAGMENT_SHADER, "resources/Shaders/identity.fs");
    if(shader.fragmentShader == 0){
        printf("failed to make fragment shader");
        exit(0);
    }

    shader.program = makeProgram(shader.vertexShader, shader.fragmentShader);
    if(shader.program == 0){
        printf("failed to make program");
        exit(0);
    }
    
    shader.uniforms.colour = glGetUniformLocation( shader.program, "colour");
    
    if( shader.uniforms.colour == -1){
        printf( "failed to locate uniform colour location");
        exit(0);
	}
    
    shader.uniforms.modelViewProjectionMatrix = glGetUniformLocation(shader.program, "modelViewProjectionMatrix");
    
    if( shader.uniforms.modelViewProjectionMatrix == -1){
        printf("failed to locate uniform modelViewProjectionMatrix");
        exit(0);
    }
    
    
    shader.attributes.pos = glGetAttribLocation( shader.program, "position");
    

}
示例#13
0
DrawTexture::DrawTexture(uint32_t width, uint32_t height,
                         const char* const szArgs,
                         const std::string sBasePath)
        : GL3LoadTestSample(width, height, szArgs, sBasePath)
{
    std::string filename;
    GLfloat* pfQuadTexCoords = quad_texture;
    GLfloat  fTmpTexCoords[sizeof(quad_texture)/sizeof(GLfloat)];
    GLenum target;
    GLboolean isMipmapped;
    GLenum glerror;
    GLubyte* pKvData;
    GLuint  kvDataLen;
    GLint sign_s = 1, sign_t = 1;
    GLint i;
    GLuint gnColorFs, gnDecalFs, gnVs;
    GLsizeiptr offset;
    KTX_dimensions dimensions;
    KTX_error_code ktxresult;
    KTX_hash_table kvtable;

    bInitialized = false;
    gnTexture = 0;
    
    filename = getAssetPath() + szArgs;    
    ktxresult = ktxLoadTextureN(filename.c_str(), &gnTexture, &target,
                               &dimensions, &isMipmapped, &glerror,
                               &kvDataLen, &pKvData);

    if (KTX_SUCCESS == ktxresult) {

        ktxresult = ktxHashTable_Deserialize(kvDataLen, pKvData, &kvtable);
        if (KTX_SUCCESS == ktxresult) {
            GLchar* pValue;
            GLuint valueLen;

            if (KTX_SUCCESS == ktxHashTable_FindValue(kvtable, KTX_ORIENTATION_KEY,
                                                      &valueLen, (void**)&pValue))
            {
                char s, t;

                if (sscanf(pValue, /*valueLen,*/ KTX_ORIENTATION2_FMT, &s, &t) == 2) {
                    if (s == 'l') sign_s = -1;
                    if (t == 'd') sign_t = -1;
                }
            }
            ktxHashTable_Destroy(kvtable);
            free(pKvData);
        }

        if (sign_s < 0 || sign_t < 0) {
            // Transform the texture coordinates to get correct image
            // orientation.
            int iNumCoords = sizeof(quad_texture) / sizeof(float);
            for (i = 0; i < iNumCoords; i++) {
                fTmpTexCoords[i] = quad_texture[i];
                if (i & 1) { // odd, i.e. a y coordinate
                    if (sign_t < 1) {
                        fTmpTexCoords[i] = fTmpTexCoords[i] * -1 + 1;
                    }
                } else { // an x coordinate
                    if (sign_s < 1) {
                        fTmpTexCoords[i] = fTmpTexCoords[i] * -1 + 1;
                    }
                }
            }
            pfQuadTexCoords = fTmpTexCoords;
        }

        uTexWidth = dimensions.width;
        uTexHeight = dimensions.height;

        if (isMipmapped)
            // Enable bilinear mipmapping.
            // TO DO: application can consider inserting a key,value pair in
            // the KTX file that indicates what type of filtering to use.
            glTexParameteri(target,
                            GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
        else
            glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

        assert(GL_NO_ERROR == glGetError());
    } else {
        std::stringstream message;

        message << "Load of texture from \"" << filename << "\" failed: ";
        if (ktxresult == KTX_GL_ERROR) {
            message << std::showbase << "GL error " << std::hex << glerror
                    << " occurred.";
        } else {
            message << ktxErrorString(ktxresult);
        }
        throw std::runtime_error(message.str());
    }

    glClearColor(0.4f, 0.4f, 0.5f, 1.0f);

    // Must have vertex data in buffer objects to use VAO's on ES3/GL Core
    glGenBuffers(1, &gnVbo);
    glBindBuffer(GL_ARRAY_BUFFER, gnVbo);

    // Create the buffer data store
    glBufferData(GL_ARRAY_BUFFER,
                 sizeof(frame_position) + sizeof(frame_color)
                 + sizeof(quad_position) + sizeof(quad_color)
                 + sizeof(quad_texture),
                 NULL, GL_STATIC_DRAW);

    glGenVertexArrays(2, gnVaos);

    // Interleave data copying and attrib pointer setup so offset is only
    // computed once.

    // Setup VAO and buffer the data for frame
    glBindVertexArray(gnVaos[FRAME]);
    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);
    offset = 0;
    glBufferSubData(GL_ARRAY_BUFFER, offset,
                    sizeof(frame_position), frame_position);
    glVertexAttribPointer(0, 3, GL_BYTE, GL_FALSE, 0, (GLvoid*)offset);
    offset += sizeof(frame_position);
    glBufferSubData(GL_ARRAY_BUFFER, offset, sizeof(frame_color), frame_color);
    glVertexAttribPointer(1, 3, GL_BYTE, GL_FALSE, 0, (GLvoid*)offset);
    offset += sizeof(frame_color);

    // Setup VAO for quad
    glBindVertexArray(gnVaos[QUAD]);
    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);
    glEnableVertexAttribArray(2);
    glBufferSubData(GL_ARRAY_BUFFER, offset,
                    sizeof(quad_position), quad_position);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)offset);
    offset += sizeof(quad_position);
    glBufferSubData(GL_ARRAY_BUFFER, offset, sizeof(quad_color), quad_color);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)offset);
    offset += sizeof(quad_color);
    glBufferSubData(GL_ARRAY_BUFFER, offset,
                    sizeof(quad_texture), pfQuadTexCoords);
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, (GLvoid*)offset);

    glBindVertexArray(0);
    try {
        makeShader(GL_VERTEX_SHADER, pszVs, &gnVs);
        makeShader(GL_FRAGMENT_SHADER, pszColorFs, &gnColorFs);
        makeProgram(gnVs, gnColorFs, &gnColProg);
        gulMvMatrixLocCP = glGetUniformLocation(gnColProg, "mvmatrix");
        gulPMatrixLocCP = glGetUniformLocation(gnColProg, "pmatrix");
        makeShader(GL_FRAGMENT_SHADER, pszDecalFs, &gnDecalFs);
        makeProgram(gnVs, gnDecalFs, &gnTexProg);
    } catch (std::exception& e) {
        (void)e; // To quiet unused variable warnings from some compilers.
        throw;
    }
    gulMvMatrixLocTP = glGetUniformLocation(gnTexProg, "mvmatrix");
    gulPMatrixLocTP = glGetUniformLocation(gnTexProg, "pmatrix");
    gulSamplerLocTP = glGetUniformLocation(gnTexProg, "sampler");
    glUseProgram(gnTexProg);
    // We're using the default texture unit 0
    glUniform1i(gulSamplerLocTP, 0);
    glDeleteShader(gnVs);
    glDeleteShader(gnColorFs);
    glDeleteShader(gnDecalFs);

    // Set the quad's mv matrix to scale by the texture size.
    // With the pixel-mapping ortho projection set below, the texture will
    // be rendered at actual size just like DrawTex*OES.
    quadMvMatrix = glm::scale(glm::mat4(),
                              glm::vec3((float)uTexWidth / 2,
                                        (float)uTexHeight / 2,
                                        1));

    assert(GL_NO_ERROR == glGetError());
    bInitialized = true;
}
示例#14
0
void atInitialize_01_draw_texture(void** ppAppData, const char* const szArgs,
                                  const char* const szBasePath)
{
    const char* filename;
	GLfloat* pfQuadTexCoords = quad_texture;
	GLfloat  fTmpTexCoords[sizeof(quad_texture)/sizeof(GLfloat)];
	GLuint texture = 0;
	GLenum target;
	GLboolean isMipmapped;
	GLenum glerror;
	GLubyte* pKvData;
	GLuint  kvDataLen;
	GLint sign_s = 1, sign_t = 1;
	GLint i;
	GLuint gnColorFs, gnDecalFs, gnVs;
	GLsizeiptr offset;
	KTX_dimensions dimensions;
	KTX_error_code ktxerror;
	KTX_hash_table kvtable;

	DrawTexture* pData = (DrawTexture*)atMalloc(sizeof(DrawTexture), 0);

	atAssert(pData);
	atAssert(ppAppData);

	*ppAppData = pData;

	pData->bInitialized = GL_FALSE;
	pData->gnTexture = 0;
	
    filename = atStrCat(szBasePath, szArgs);
    
    if (filename != NULL) {
        ktxerror = ktxLoadTextureN(filename, &pData->gnTexture, &target,
                                   &dimensions, &isMipmapped, &glerror,
                                   &kvDataLen, &pKvData);

        if (KTX_SUCCESS == ktxerror) {

            ktxerror = ktxHashTable_Deserialize(kvDataLen, pKvData, &kvtable);
            if (KTX_SUCCESS == ktxerror) {
                GLchar* pValue;
                GLuint valueLen;

                if (KTX_SUCCESS == ktxHashTable_FindValue(kvtable, KTX_ORIENTATION_KEY,
                                                          &valueLen, (void**)&pValue))
                {
                    char s, t;

                    if (sscanf(pValue, /*valueLen,*/ KTX_ORIENTATION2_FMT, &s, &t) == 2) {
                        if (s == 'l') sign_s = -1;
                        if (t == 'd') sign_t = -1;
                    }
                }
                ktxHashTable_Destroy(kvtable);
                free(pKvData);
            }

            if (sign_s < 0 || sign_t < 0) {
                // Transform the texture coordinates to get correct image orientation.
                int iNumCoords = sizeof(quad_texture) / sizeof(float);
                for (i = 0; i < iNumCoords; i++) {
                    fTmpTexCoords[i] = quad_texture[i];
                    if (i & 1) { // odd, i.e. a y coordinate
                        if (sign_t < 1) {
                            fTmpTexCoords[i] = fTmpTexCoords[i] * -1 + 1;
                        }
                    } else { // an x coordinate
                        if (sign_s < 1) {
                            fTmpTexCoords[i] = fTmpTexCoords[i] * -1 + 1;
                        }
                    }
                }
                pfQuadTexCoords = fTmpTexCoords;
            }

            pData->iTexWidth = dimensions.width;
            pData->iTexHeight = dimensions.height;

            if (isMipmapped) 
                /* Enable bilinear mipmapping */
                /* TO DO: application can consider inserting a key,value pair in the KTX
                 * that indicates what type of filtering to use.
                 */
                glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
            else
                glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
            glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

            atAssert(GL_NO_ERROR == glGetError());
        } else {
            char message[1024];
            int maxchars = sizeof(message)/sizeof(char);
            int nchars;

            nchars = snprintf(message, maxchars, "Load of texture \"%s\" failed: ",
                              filename);
			maxchars -= nchars;
            if (ktxerror == KTX_GL_ERROR) {
                nchars += snprintf(&message[nchars], maxchars, "GL error %#x occurred.", glerror);
			} else {
				nchars += snprintf(&message[nchars], maxchars, "%s.", ktxErrorString(ktxerror));
			}
            atMessageBox(message, "Texture load failed", AT_MB_OK|AT_MB_ICONERROR);

            pData->iTexWidth = pData->iTexHeight = 50;
            pData->gnTexture = 0;
        }
        
        atFree((void*)filename, NULL);
    } /* else
       Out of memory. In which case, a message box is unlikely to work. */

    glClearColor(0.4f, 0.4f, 0.5f, 1.0f);

    // Must have vertex data in buffer objects to use VAO's on ES3/GL Core
	glGenBuffers(1, &pData->gnVbo);
	glBindBuffer(GL_ARRAY_BUFFER, pData->gnVbo);

	// Create the buffer data store
	glBufferData(GL_ARRAY_BUFFER,
				 sizeof(frame_position) + sizeof(frame_color) + sizeof(quad_position)
				 + sizeof(quad_color) + sizeof(quad_texture),
				 NULL, GL_STATIC_DRAW);

	glGenVertexArrays(2, pData->gnVaos);

	// Interleave data copying and attrib pointer setup so offset is only computed once.

	// Setup VAO and buffer the data for frame
	glBindVertexArray(pData->gnVaos[FRAME]);
	glEnableVertexAttribArray(0);
	glEnableVertexAttribArray(1);
	offset = 0;
	glBufferSubData(GL_ARRAY_BUFFER, offset, sizeof(frame_position), frame_position);
	glVertexAttribPointer(0, 3, GL_BYTE, GL_FALSE, 0, (GLvoid*)offset);
	offset += sizeof(frame_position);
	glBufferSubData(GL_ARRAY_BUFFER, offset, sizeof(frame_color), frame_color);
	glVertexAttribPointer(1, 3, GL_BYTE, GL_FALSE, 0, (GLvoid*)offset);
	offset += sizeof(frame_color);

	// Setup VAO for quad
	glBindVertexArray(pData->gnVaos[QUAD]);
	glEnableVertexAttribArray(0);
	glEnableVertexAttribArray(1);
	glEnableVertexAttribArray(2);
	glBufferSubData(GL_ARRAY_BUFFER, offset, sizeof(quad_position), quad_position);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)offset);
	offset += sizeof(quad_position);
	glBufferSubData(GL_ARRAY_BUFFER, offset, sizeof(quad_color), quad_color);
	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)offset);
	offset += sizeof(quad_color);
	glBufferSubData(GL_ARRAY_BUFFER, offset, sizeof(quad_texture), pfQuadTexCoords);
	glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, (GLvoid*)offset);

	glBindVertexArray(0);
	if (makeShader(GL_VERTEX_SHADER, pszVs, &gnVs)) {
		if (makeShader(GL_FRAGMENT_SHADER, pszColorFs, &gnColorFs)) {
			if (makeProgram(gnVs, gnColorFs, &pData->gnColProg)) {
				pData->gulMvMatrixLocCP = glGetUniformLocation(pData->gnColProg, "mvmatrix");
				pData->gulPMatrixLocCP = glGetUniformLocation(pData->gnColProg, "pmatrix");
			}
		}
		if (makeShader(GL_FRAGMENT_SHADER, pszDecalFs, &gnDecalFs)) {
			if (makeProgram(gnVs, gnDecalFs, &pData->gnTexProg)) {
				pData->gulMvMatrixLocTP = glGetUniformLocation(pData->gnTexProg, "mvmatrix");
				pData->gulPMatrixLocTP = glGetUniformLocation(pData->gnTexProg, "pmatrix");
				pData->gulSamplerLocTP = glGetUniformLocation(pData->gnTexProg, "sampler");
				glUseProgram(pData->gnTexProg);
				// We're using the default texture unit 0
				glUniform1i(pData->gulSamplerLocTP, 0);
			}
		}
		glDeleteShader(gnVs);
		glDeleteShader(gnColorFs);
		glDeleteShader(gnDecalFs);
	}

	// Set the quad's mv matrix to scale by the texture size.
	// With the pixel-mapping ortho projection set below, the texture will
	// be rendered at actual size just like DrawTex*OES.
	for (i = 0; i < 16; i++) {
		pData->fQuadMvMatrix[i] = atIdentity[i];
		pData->fFrameMvMatrix[i] = atIdentity[i];
	}
	pData->fQuadMvMatrix[0*4 + 0] = (float)pData->iTexWidth / 2;
	pData->fQuadMvMatrix[1*4 + 1] = (float)pData->iTexHeight / 2;

	atAssert(GL_NO_ERROR == glGetError());
	pData->bInitialized = GL_TRUE;
}
示例#15
0
文件: main.cpp 项目: jankdc/cee
int main(int argc, char ** argv)
{
    auto pathToRom = std::string();

    if (argc == 2)
    {
        pathToRom = argv[1];
    }
    else
    {
        printf("Chip8 Error: Wrong number of arguments\n");
        return -1;
    }

    sf::SoundBuffer beepSnd;
    if (! beepSnd.loadFromFile("data/sounds/beep.wav"))
    {
        printf("Chip8 Error: Can't load the beeping sound.\n");
        return -1;
    }

    sf::Sound sndSrc;
    sndSrc.setBuffer(beepSnd);
    sndSrc.setLoop(false);

    auto window = setupWindow(WIDTH, HEIGHT, TITLE);

    cee::Chip8 chip;
    chip.loadProgram(readAllBytes(pathToRom.c_str()));

    constexpr GLfloat pxVerts[] =
    {
        -1.0f,  1.0f, 0.0f, // Top Left
         1.0f,  1.0f, 0.0f, // Top Right
        -1.0f, -1.0f, 0.0f, // Bottom Left
         1.0f, -1.0f, 0.0f  // Bottom Right
    };

    constexpr GLuint pxIndices[] =
    {
        0, 1, 2,
        2, 1, 3
    };

    // Initialize the VAO and other buffers associated
    // with drawing an emulated pixel.
    GLuint vao, vbo, ibo;
    glGenVertexArrays(1, &vao);

    glBindVertexArray(vao);
    {
        glGenBuffers(1, &vbo);
        glGenBuffers(1, &ibo);

        // VBO
        glBindBuffer(GL_ARRAY_BUFFER, vbo);
        glBufferData(GL_ARRAY_BUFFER, sizeof(pxVerts), &pxVerts, GL_STATIC_DRAW);

        // IBO
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(pxIndices), &pxIndices, GL_STATIC_DRAW);

        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), nullptr);
        glEnableVertexAttribArray(0);
    }
    glBindVertexArray(0);

    // Current Vertex Shader
    const auto pxVertexSrc = readAllChars("data/shaders/px_vertex.glsl");
    const auto pxVertex = makeShader(GL_VERTEX_SHADER, pxVertexSrc);

    // Current Fragment Shader
    const auto pxFragmentSrc = readAllChars("data/shaders/px_fragment.glsl");
    const auto pxFragment = makeShader(GL_FRAGMENT_SHADER, pxFragmentSrc);

    // Current Shader Program
    const auto pxProgram = makeProgram({pxVertex, pxFragment});
    glUseProgram(pxProgram);

    glfwShowWindow(window);
    while (! glfwWindowShouldClose(window))
    {
        chip.updateKeys(getKeyStates(window));
        chip.updateCycle();

        if (chip.isBeeping() && sndSrc.getStatus() != sf::SoundSource::Playing)
            sndSrc.play();

        // Clear back buffer and background color.
        glClear(GL_COLOR_BUFFER_BIT);
        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

        glBindVertexArray(vao);
        const auto gfx = chip.getGfx();
        for (int i = 0; i < 32; ++i)
        {
            // Maps the width resolution [0-HEIGHT] to [-1.0-1.0]
            auto y = - mapRangeHeight(i);
            auto l = i * 64;

            for (int j = 0; j < 64; ++j)
            {
                if (gfx[l + j] == 1)
                {
                    // Maps the width resolution [0-WIDTH] to [-1.0-1.0]
                    auto x = mapRangeWidth(j);
                    auto ident = glGetUniformLocation(pxProgram, "PxModel");
                    auto model = glm::mat4(1.0f);
                    model = glm::translate(model, glm::vec3(x, y, 0.0f));
                    model = glm::scale(model, glm::vec3(PX_WIDTH, PX_HEIGHT, 1.0f));
                    glUniformMatrix4fv(ident, 1, GL_FALSE, glm::value_ptr(model));
                    glDrawElements(GL_TRIANGLES, sizeof(pxIndices), GL_UNSIGNED_INT, nullptr);
                }
            }
        }
        glBindVertexArray(0);

        glfwSwapBuffers(window);
        glfwPollEvents();
    }

    // Cleanup resources
    glDeleteProgram(pxProgram);
    glDeleteShader(pxVertex);
    glDeleteShader(pxFragment);
    glDeleteVertexArrays(1, &vao);
    glDeleteBuffers(1, &ibo);
    glDeleteBuffers(1, &vbo);
    glfwTerminate();
    return 0;
}
示例#16
0
void meshModels::cacheCylinder(float vertsX[], float vertsY[], float depth)
{
	dir = TRUE;
	cacheEndCap( vertsX, vertsY, 0.0f);
	dir = FALSE;
	cacheEndCap( vertsX, vertsY, depth);
	dir = FALSE;

	// objects to build our vertices in
	vertex_t vertA, vertB, vertC;
	polygon_t poly;
	int i = 0;
	int j;
	int faceCount;

	// find out how many verts we have
	int vcount = model.verts.size();
	int endGon = vcount; // and saving the starting vertice index for later

	//record all three points as a triangle in our structure
	poly.a = vcount;
	poly.b = vcount +1;
	poly.c = vcount +2;

	// we need to start with two verts because then 
	//we only need to add 2 verts to get 2 new triangles in the for loop

	// build our first vertex
	vertA.x = vertsX[i];
	vertA.y = vertsY[i];
	vertA.z = 0.0f;
	// push it into our array
	model.verts.reserve(poly.a);
	model.verts.push_back(vertA);

	//build our third vertex
	vertB.x = vertsX[i];
	vertB.y = vertsY[i];
	vertB.z = depth;
	// push it into our array
	model.verts.reserve(poly.b);
	model.verts.push_back(vertB);
	
	i++;

	// build a cylinder 2 triangles at a time
	for( j = 0; j < 62; ++j)
	{
		// ensure our array iterator is not too large
		if(i>=32)
			i = 0;

		//record all three points as a triangle in our structure
		poly.a = vcount;
		poly.b = vcount +1;
		poly.c = vcount +2;

		//build our second vertex
		vertC.x = vertsX[i];
		vertC.y = vertsY[i];
		vertC.z = 0.0f;
		// push it into our array
		model.verts.reserve(poly.c);
		model.verts.push_back(vertC);


		// record the triangle
		model.polys.reserve(j);
		model.polys.push_back(poly);

		faceCount = model.polys.size()-1;

		calculateFaceNormal(faceCount);

		j++; // advance to the next polygon
	
		// vertex A is really the old vertex b so lets record the change here
		poly.a = poly.b;

		vertB.x = vertsX[i];
		vertB.y = vertsY[i];
		vertB.z = depth;
		poly.b = model.verts.size(); // set the iterator for the new vertex
		model.verts.reserve(poly.b);
		model.verts.push_back(vertB);

		// VertC is the same and remains unchanged
		// lets store our triangle
		model.polys.reserve(j);
		model.polys.push_back(poly);

		faceCount = model.polys.size()-1;

		calculateFaceNormal(faceCount);

		vcount = vcount +2;
		i++;
	}

	// add our last two triangles using existing verts
	poly.a = model.verts.size() - 2;
	poly.b = model.verts.size() - 1;
	poly.c = endGon;

	model.polys.reserve(vcount);
	model.polys.push_back(poly);

	faceCount = model.polys.size()-1;
	calculateFaceNormal(faceCount);

	// add our last two triangles using existing verts
	poly.a = model.verts.size() - 1;
	poly.b = endGon + 1;
	poly.c = endGon;

	model.polys.reserve(vcount + 1);
	model.polys.push_back(poly);

	faceCount = model.polys.size()-1;
	calculateFaceNormal(faceCount);

	normalizeVerts();

	makeShader();
	makeBuffer();
}
示例#17
0
void atInitialize_02_cube(void** ppAppData, const char* const args)
{
	GLuint texture = 0;
	GLenum target;
	GLenum glerror;
	GLboolean isMipmapped;
	GLuint gnDecalFs, gnVs;
	GLsizeiptr offset;
	KTX_error_code ktxerror;

	CubeTextured* pData = (CubeTextured*)atMalloc(sizeof(CubeTextured), 0);

	atAssert(pData);
	atAssert(ppAppData);

	*ppAppData = pData;

	pData->bInitialized = GL_FALSE;
	pData->gnTexture = 0;

	ktxerror = ktxLoadTextureN(args, &texture, &target, NULL, &isMipmapped, &glerror,
		                       0, NULL);

	if (KTX_SUCCESS == ktxerror) {
		if (target != GL_TEXTURE_2D) {
			/* Can only draw 2D textures */
			glDeleteTextures(1, &texture);
			return;
		}

		if (isMipmapped) 
			/* Enable bilinear mipmapping */
			/* TO DO: application can consider inserting a key,value pair in the KTX
			 * file that indicates what type of filtering to use.
			 */
			glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
		else
			glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

		atAssert(GL_NO_ERROR == glGetError());
	} else {
		char message[1024];
		int maxchars = sizeof(message)/sizeof(char);
		int nchars;

		nchars = snprintf(message, maxchars, "Load of texture \"%s\" failed: %s.",
						  args, ktxErrorString(ktxerror));
		if (ktxerror == KTX_GL_ERROR) {
			maxchars -= nchars;
			nchars += snprintf(&message[nchars], maxchars, " GL error is %#x.", glerror);
		}
		atMessageBox(message, "Texture load failed", AT_MB_OK|AT_MB_ICONERROR);
	}

	/* By default dithering is enabled. Dithering does not provide visual improvement 
	 * in this sample so disable it to improve performance. 
	 */
	glDisable(GL_DITHER);

	glEnable(GL_CULL_FACE);
	glClearColor(0.2f,0.3f,0.4f,1.0f);

	// Create a VAO and bind it.
	glGenVertexArrays(1, &pData->gnVao);
	glBindVertexArray(pData->gnVao);

	// Must have vertex data in buffer objects to use VAO's on ES3/GL Core
	glGenBuffers(1, &pData->gnVbo);
	glBindBuffer(GL_ARRAY_BUFFER, pData->gnVbo);
	// Must be done after the VAO is bound
	// Use the same buffer for vertex attributes and element indices.
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, pData->gnVbo);

	// Create the buffer data store. 
	glBufferData(GL_ARRAY_BUFFER,
				 sizeof(cube_face) + sizeof(cube_color) + sizeof(cube_texture)
				 + sizeof(cube_normal) + sizeof(cube_index_buffer),
				 NULL, GL_STATIC_DRAW);

	// Interleave data copying and attrib pointer setup so offset is only computed once.
	glEnableVertexAttribArray(0);
	glEnableVertexAttribArray(1);
	glEnableVertexAttribArray(2);
	glEnableVertexAttribArray(3);
	offset = 0;
	glBufferSubData(GL_ARRAY_BUFFER, offset, sizeof(cube_face), cube_face);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)offset);
	offset += sizeof(cube_face);
	glBufferSubData(GL_ARRAY_BUFFER, offset, sizeof(cube_color), cube_color);
	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)offset);
	offset += sizeof(cube_color);
	glBufferSubData(GL_ARRAY_BUFFER, offset, sizeof(cube_texture), cube_texture);
	glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, (GLvoid*)offset);
	offset += sizeof(cube_texture);
	glBufferSubData(GL_ARRAY_BUFFER, offset, sizeof(cube_normal), cube_normal);
	glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)offset);
	offset += sizeof(cube_normal);
	pData->iIndicesOffset = offset;
	// Either of the following can be used to buffer the data.
	glBufferSubData(GL_ARRAY_BUFFER, offset, sizeof(cube_index_buffer), cube_index_buffer);
	//glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, offset, sizeof(cube_index_buffer), cube_index_buffer);

	if (makeShader(GL_VERTEX_SHADER, pszVs, &gnVs)) {
		if (makeShader(GL_FRAGMENT_SHADER, pszDecalFs, &gnDecalFs)) {
			if (makeProgram(gnVs, gnDecalFs, &pData->gnTexProg)) {
				pData->gulMvMatrixLocTP = glGetUniformLocation(pData->gnTexProg, "mvmatrix");
				pData->gulPMatrixLocTP = glGetUniformLocation(pData->gnTexProg, "pmatrix");
				pData->gulSamplerLocTP = glGetUniformLocation(pData->gnTexProg, "sampler");
				glUseProgram(pData->gnTexProg);
				// We're using the default texture unit 0
				glUniform1i(pData->gulSamplerLocTP, 0);
			}
		}
		glDeleteShader(gnVs);
		glDeleteShader(gnDecalFs);
	}

	atAssert(GL_NO_ERROR == glGetError());
	pData->bInitialized = GL_TRUE;
}