bool GuiButton::onEvent(const GEvent& event) { switch (event.type) { case GEventType::MOUSE_BUTTON_DOWN: m_down = true; // invoke the pre-event handler m_callback.execute(); debugAssertGLOk(); fireEvent(GEventType::GUI_DOWN); debugAssertGLOk(); return true; case GEventType::MOUSE_BUTTON_UP: fireEvent(GEventType::GUI_UP); // Only trigger an action if the mouse was still over the control if (m_down && m_rect.contains(Vector2(event.button.x, event.button.y))) { fireEvent(GEventType::GUI_ACTION); } m_down = false; return true; } return false; }
void Shader::ShaderProgram::link() { glProgramObject = glCreateProgram(); debugAssertGLOk(); // Attach for (int s = 0; s < STAGE_COUNT; ++s) { if (glShaderObject[s]) { glAttachShader(glProgramObject, glShaderObject[s]); } debugAssertGLOk(); } // Link glLinkProgram(glProgramObject); debugAssertGLOk(); // Read back messages GLint linked; glGetProgramiv(glProgramObject, GL_LINK_STATUS, &linked); debugAssertGLOk(); GLint maxLength = 0, length = 0; glGetProgramiv(glProgramObject, GL_INFO_LOG_LENGTH, &maxLength); GLchar* pInfoLog = (GLchar *)malloc((maxLength + 1) * sizeof(GLcharARB)); glGetProgramInfoLog(glProgramObject, maxLength, &length, pInfoLog); debugAssertGLOk(); messages += String(pInfoLog); ok = ok && (linked == GL_TRUE); free(pInfoLog); pInfoLog = nullptr; }
RenderbufferRef Renderbuffer::createEmpty( const std::string& _name, const int _width, const int _height, const G3D::ImageFormat* _format) { // New Renderbuffer ID GLuint _imageID; // Save old renderbuffer state GLint origBuffer; glGetIntegerv(GL_RENDERBUFFER_BINDING, &origBuffer); // Generate buffer glGenRenderbuffers(1, &_imageID); debugAssertGLOk(); // Bind the buffer glBindRenderbuffer(GL_RENDERBUFFER, _imageID); debugAssertGLOk(); // Allocate storage for it glRenderbufferStorage(GL_RENDERBUFFER, _format->openGLFormat, _width, _height); // Check for successful generation (ie, no INVALID_OPERATION) debugAssertGLOk(); // Restore renderbuffer state glBindRenderbuffer(GL_RENDERBUFFER, origBuffer); debugAssertGLOk(); // Create new renderbuffer return Ref(new Renderbuffer(_name, _imageID, _format, _width, _height)); }
BufferTexture::~BufferTexture() { glBindTexture(GL_TEXTURE_BUFFER, m_textureID); debugAssertGLOk(); glTexBuffer(GL_TEXTURE_BUFFER, m_buffer->format()->openGLFormat, 0); debugAssertGLOk(); glBindTexture(GL_TEXTURE_BUFFER, 0); debugAssertGLOk(); glDeleteTextures(1, &m_textureID); debugAssertGLOk(); m_textureID = 0; }
void Framebuffer::set(AttachmentPoint ap, const TextureRef& texture) { if (texture.isNull()) { // We're in the wrong overload set(ap, (void*)NULL); return; } // Get current framebuffer GLint origFB = glGetInteger(GL_FRAMEBUFFER_BINDING_EXT); // If we aren't already bound, bind us now if (origFB != (GLint)openGLID()) { // Bind this framebuffer glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, openGLID()); debugAssertGLOk(); } // Check for completeness if (numAttachments == 0) { // This is the first attachment. // Set texture height/width m_width = texture->texelWidth(); m_height = texture->texelHeight(); } else { // Verify same dimensions debugAssertM((texture->texelWidth() != width()) || (texture->texelHeight() != height()), "All attachments bound to a Framebuffer must " "have identical dimensions!"); } if (! attachmentTable.containsKey(ap)) { attachmentTable.set(ap, Attachment(texture)); } // Bind texture to framebuffer glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, ap, texture->openGLTextureTarget(), texture->openGLID(), 0); debugAssertGLOk(); // If we were already bound, don't bother restoring if (origFB != (GLint)openGLID()) { // Bind original framebuffer glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, origFB); } debugAssertGLOk(); }
shared_ptr<BufferTexture> BufferTexture::create(const std::string& name, const shared_ptr<GLPixelTransferBuffer>& buffer) { debugAssertM(GLCaps::maxTextureBufferSize() > 0, "Buffer Textures not supported by your driver."); alwaysAssertM(isValidBufferTextureImageFormat(buffer->format()), G3D::format("Invalidly formatted buffer passed to BufferTexture::create(), format %s is unsupported.", buffer->format()->name().c_str()) ); GLuint textureID = Texture::newGLTextureID(); /** Load the data */ glBindTexture(GL_TEXTURE_BUFFER, textureID); debugAssertGLOk(); glTexBuffer(GL_TEXTURE_BUFFER, buffer->format()->openGLFormat, buffer->glBufferID()); debugAssertGLOk(); glBindTexture(GL_TEXTURE_BUFFER, 0); return shared_ptr<BufferTexture>(new BufferTexture(name, buffer, textureID)); }
bool WidgetManager::onEvent(const GEvent& event, WidgetManager::Ref& a, WidgetManager::Ref& b) { a->beginLock(); if (b) { b->beginLock(); } int numManagers = isNull(b) ? 1 : 2; // Process each for (int k = 0; k < numManagers; ++k) { Array<Widget::Ref >& array = (k == 0) ? a->m_moduleArray : b->m_moduleArray; for (int i = array.size() - 1; i >= 0; --i) { if (array[i]->onEvent(event)) { debugAssertGLOk(); if (b) { b->endLock(); } a->endLock(); return true; } } } if (b) { b->endLock(); } a->endLock(); return false; }
Demo::Demo(App* _app) : GApplet(_app), app(_app) { // Allocate the two VARAreas used in this demo varStatic = VARArea::create(1024 * 640 * 5, VARArea::WRITE_ONCE); varStream = VARArea::create(1024 * 1280 * 5, VARArea::WRITE_EVERY_FRAME); debugAssertGLOk(); debugAssert(varStatic.notNull()); debugAssert(varStream.notNull()); }
// Called before the application loop begins. Load data here and // not in the constructor so that common exceptions will be // automatically caught. void App::onInit() { GApp::onInit(); debugAssertGLOk(); setFrameDuration(1.0f / 120.0f); // Call setScene(shared_ptr<Scene>()) or setScene(MyScene::create()) to replace // the default scene here. showRenderingStats = false; SVO::Specification spec; spec.encoding[GBuffer::Field::LAMBERTIAN].format = ImageFormat::RGBA16F(); spec.encoding[GBuffer::Field::WS_NORMAL].format = ImageFormat::RGBA16F(); spec.encoding[GBuffer::Field::GLOSSY].format = ImageFormat::RGBA16F(); //spec.encoding[GBuffer::Field::WS_FACE_NORMAL].format = ImageFormat::RG16F(); //Test. 2xFP16 for atomic min # if 0 //def G3D_DEBUG // Not used, but the program crashes without this spec.encoding[GBuffer::Field::WS_POSITION].format = ImageFormat::RGBA16F(); # endif spec.dimension = Texture::DIM_3D; debugAssertGLOk(); m_svo = SVO::create(spec, "SVO", true); makeGUI(); // For higher-quality screenshots: // developerWindow->videoRecordDialog->setScreenShotFormat("PNG"); // developerWindow->videoRecordDialog->setCaptureGui(false); developerWindow->cameraControlWindow->moveTo(Point2(developerWindow->cameraControlWindow->rect().x0(), 0)); loadScene( //"G3D Sponza" //"G3D Cornell Box" // Load something simple "Test Scene" //developerWindow->sceneEditorWindow->selectedSceneName() // Load the first scene encountered ); dynamic_pointer_cast<DefaultRenderer>(m_renderer)->setOrderIndependentTransparency(false); }
void Framebuffer::set(AttachmentPoint ap, const void* n) { debugAssert(n == NULL); // Get current framebuffer GLint origFB = glGetInteger(GL_FRAMEBUFFER_BINDING_EXT); debugAssertGLOk(); // If we aren't already bound, bind us now if (origFB != (GLint)openGLID()) { // Bind this framebuffer glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, openGLID()); debugAssertGLOk(); } if (attachmentTable.containsKey(ap)) { // Detach if (attachmentTable[ap].type == Attachment::TEXTURE) { glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, ap, GL_TEXTURE_2D, 0, 0); debugAssertGLOk(); if (attachmentTable[ap].hadAutoMipMap) { attachmentTable[ap].texture->setAutoMipMap(true); } } else { glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, ap, GL_RENDERBUFFER_EXT, 0); debugAssertGLOk(); } --numAttachments; } else { // Wipe our record for that slot attachmentTable.remove(ap); } // If we were already bound, don't bother restoring if (origFB != (GLint)openGLID()) { // Bind original framebuffer glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, origFB); debugAssertGLOk(); } }
FramebufferRef Framebuffer::create(const std::string& _name) { GLuint _framebufferID; // Generate Framebuffer glGenFramebuffersEXT(1, &_framebufferID); debugAssertGLOk(); return new Framebuffer(_name, _framebufferID); }
void Viewer::onGraphics(RenderDevice* rd) { LightingParameters lighting(G3D::toSeconds(11, 00, 00, AM)); rd->setProjectionAndCameraMatrix(app->debugCamera); // Cyan background rd->setColorClearValue(Color3(0.1f, 0.5f, 1.0f)); rd->clear(app->sky.isNull(), true, true); if (app->sky.notNull()) { app->sky->render(rd, lighting); } rd->enableLighting(); rd->setLight(0, GLight::directional(lighting.lightDirection, lighting.lightColor)); rd->setAmbientLightColor(lighting.ambient); CoordinateFrame camera = rd->getCameraToWorldMatrix(); app->bumpShader->args.set("wsLightPos", Vector4(lighting.lightDirection, 0)); app->bumpShader->args.set("wsEyePos", camera.translation); app->bumpShader->args.set("texture", app->textureMap); app->bumpShader->args.set("normalBumpMap", app->normalBumpMap); app->bumpShader->args.set("reflectivity", 0);//0.35); app->bumpShader->args.set("specularity", 0);//0.4); app->bumpShader->args.set("bumpScale", bumpScale); app->bumpShader->args.set("environmentMap", app->sky->getEnvironmentMap()); rd->setShader(app->bumpShader); debugAssertGLOk(); for (int e = 0; e < entityArray.size(); ++e) { entityArray[e]->render(rd); debugAssertGLOk(); } rd->setShader(NULL); rd->disableLighting(); if (app->sky.notNull()) { app->sky->renderLensFlare(rd, lighting); } }
void Shader::ShaderProgram::init(const Array<PreprocessedShaderSource>& pss, const String& preambleAndMacroString, const Args& args, const Table<int, String>& indexToNameTable){ ok = true; debugAssertGLOk(); if (! GLCaps::supports_GL_ARB_shader_objects()) { messages = "This graphics card does not support GL_ARB_shader_objects."; ok = false; return; } debugAssertGLOk(); Array<String> fullCode; compile(pss, preambleAndMacroString, args, indexToNameTable, fullCode); debugAssertGLOk(); if (ok) { link(); if ( !ok) { debugPrintf("Shader code:\n"); for (int i = 0; i < STAGE_COUNT; ++i) { debugPrintf("Stage %d:\n", i); debugPrintf("%s\n\n", fullCode[i].c_str()); } } } debugAssertGLOk(); if (ok) { addActiveUniformsFromProgram(); debugAssertGLOk(); addUniformsFromSource(pss, args); debugAssertGLOk(); } if (ok) { addActiveAttributesFromProgram(); debugAssertGLOk(); addVertexAttributesFromSource(pss); debugAssertGLOk(); } debugAssertGLOk(); logPrintf("%s\n", messages.c_str()); }
RenderbufferRef Renderbuffer::fromGLRenderbuffer( const std::string& _name, const GLuint _imageID, const G3D::ImageFormat* _format) { GLint w, h; // Extract the width and height glGetRenderbufferParameteriv(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_WIDTH_EXT, &w); glGetRenderbufferParameteriv(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_WIDTH_EXT, &h); debugAssertGLOk(); // Create new renderbuffer return RenderBufferRef(new Renderbuffer(_name, _imageID, _format, w, h)); }
void SDLWindow::reallyMakeCurrent() const { # ifdef G3D_WIN32 if (wglMakeCurrent(_Win32HDC, _glContext) == FALSE) { debugAssertM(false, "Failed to set context"); } # elif defined(G3D_LINUX) if (! glXMakeCurrent(_X11Display, _X11Window, _glContext)) { //debugAssertM(false, "Failed to set context"); // only check OpenGL as False seems to be returned when // context is already current debugAssertGLOk(); } # elif defined(G3D_OSX) # endif }
void VideoOutput::append(RenderDevice* rd, bool backbuffer) { debugAssert(rd->width() == m_settings.width); debugAssert(rd->height() == m_settings.height); RenderDevice::ReadBuffer old = rd->readBuffer(); if (backbuffer) { rd->setReadBuffer(RenderDevice::READ_BACK); } else { rd->setReadBuffer(RenderDevice::READ_FRONT); } debugAssertGLOk(); // TODO: Optimize using GLPixelTransferBuffer and glReadPixels instead of screenshotPic shared_ptr<Image> image = rd->screenshotPic(false, false); rd->setReadBuffer(old); shared_ptr<CPUPixelTransferBuffer> imageBuffer = image->toPixelTransferBuffer(); encodeFrame(static_cast<const uint8*>(imageBuffer->buffer()), imageBuffer->format(), true); }
void Profiler::beginGFX(const std::string& name) { if (! m_supportsQuery || ! m_enabled) { return; } alwaysAssertM(m_currentGFX == "", "There is already a GFX task named " + m_currentCPU + " pending."); alwaysAssertM(! m_gfxTask.contains(name, m_frameNum), "A GFX task named " + name + " was already timed this frame."); debugAssertGLOk(); if (m_queryFreelist.size() == 0) { // Allocate some more query objects const int N = 10; m_queryFreelist.resize(N); glGenQueries(N, m_queryFreelist.getCArray()); } m_currentGFX = name; GLint query = m_queryFreelist.pop(); m_pendingQueries.append(Pair(name, query)); glBeginQuery(GL_TIME_ELAPSED_EXT, query); }
// glInterleavedArrays with 16-bit indices (should be the fastest indexed version) float measureDrawElementsVBOIPerformance(Model& model, bool use_glInterleavedArrays) { bool hasVBO = (strstr((char*)glGetString(GL_EXTENSIONS), "GL_ARB_vertex_buffer_object") != NULL) && (glGenBuffersARB != NULL) && (glBufferDataARB != NULL) && (glDeleteBuffersARB != NULL); if (! hasVBO) { return 0.0; } // Load the vertex arrays // Number of indices const int N = (int)model.cpuIndex.size(); // Number of vertices const int V = (int)model.cpuVertex.size(); GLuint vbo, indexBuffer; glGenBuffersARB(1, &vbo); glGenBuffersARB(1, &indexBuffer); glPushAttrib(GL_ALL_ATTRIB_BITS); glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS); size_t vertexSize = V * sizeof(float) * 3; size_t normalSize = V * sizeof(float) * 3; size_t colorSize = V * sizeof(float) * 4; size_t texCoordSize = V * sizeof(float) * 2; size_t totalSize = vertexSize + normalSize + texCoordSize + colorSize; // Pointers relative to the start of the vbo in video memory used // for manually interleaving GLintptrARB texCoordPtr = 0; GLintptrARB colorPtr = texCoordPtr + 2 * sizeof(float); GLintptrARB normalPtr = colorPtr + 4 * sizeof(float); GLintptrARB vertexPtr = normalPtr + 3 * sizeof(float); GLintptrARB indexPtr = 0; // Upload data glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, indexBuffer); glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, N * sizeof(unsigned short), &model.cpuIndex16[0], GL_STATIC_DRAW_ARB); glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo); float* interleave = (float*)malloc(totalSize); // Interleave the buffers in memory float* ptr = interleave; for (int i = 0; i < V; ++i) { ptr[0] = model.cpuTexCoord[i].x; ++ptr; ptr[0] = model.cpuTexCoord[i].y; ++ptr; ptr[0] = model.cpuColor[i].x; ++ptr; ptr[0] = model.cpuColor[i].y; ++ptr; ptr[0] = model.cpuColor[i].z; ++ptr; ptr[0] = model.cpuColor[i].w; ++ptr; ptr[0] = model.cpuNormal[i].x; ++ptr; ptr[0] = model.cpuNormal[i].y; ++ptr; ptr[0] = model.cpuNormal[i].z; ++ptr; ptr[0] = model.cpuVertex[i].x; ++ptr; ptr[0] = model.cpuVertex[i].y; ++ptr; ptr[0] = model.cpuVertex[i].z; ++ptr; } glBufferDataARB(GL_ARRAY_BUFFER_ARB, totalSize, interleave, GL_STATIC_DRAW_ARB); free(interleave); configureCameraAndLights(); float k = 0; double t0 = 0, t1 = 0; for (int j = 0; j < frames + 1; ++j) { if (j == 1) { t0 = System::time(); } k += kstep; glClearColor(1.0f, 1.0f, 1.0f, 0.04f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, model.textureID); glEnableClientState(GL_NORMAL_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); if (use_glInterleavedArrays) { // Use old-style OpenGL interleaving glInterleavedArrays(GL_T2F_C4F_N3F_V3F, 0, (void*)0); } else { GLsizei stride = (3+3+4+2) * sizeof(float); // Manually interleave, which gives more flexibility glTexCoordPointer(2, GL_FLOAT, stride, (void*)texCoordPtr); glColorPointer (4, GL_FLOAT, stride, (void*)colorPtr); glNormalPointer (GL_FLOAT, stride, (void*)normalPtr); glVertexPointer (3, GL_FLOAT, stride, (void*)vertexPtr); } for (int c = 0; c < count; ++c) { glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(c - (count - 1) / 2.0, 0, -2); glRotatef(k * ((c & 1) * 2 - 1) + 90, 0, 1, 0); debugAssertGLOk(); glDrawElements(GL_TRIANGLES, N, GL_UNSIGNED_SHORT, (void*)indexPtr); debugAssertGLOk(); } glSwapBuffers(); } glFinish(); t1 = System::time(); glPopClientAttrib(); glPopAttrib(); glDeleteBuffersARB(1, &indexBuffer); glDeleteBuffersARB(1, &vbo); return frames / (t1 - t0); }
VARArea::VARArea(size_t _size, UsageHint hint) : size(_size) { renderDevice = NULL; // See if we've determined the mode yet. if (mode == UNINITIALIZED) { if (GLCaps::supports_GL_ARB_vertex_buffer_object() && (glGenBuffersARB != NULL) && (glBufferDataARB != NULL) && (glDeleteBuffersARB != NULL) && ! GLCaps::hasBug_slowVBO()) { mode = VBO_MEMORY; } else { mode = MAIN_MEMORY; } } _sizeOfAllVARAreasInMemory += size; switch (mode) { case VBO_MEMORY: { //glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT); glGenBuffersARB(1, &glbuffer); glBindBufferARB(GL_ARRAY_BUFFER_ARB, glbuffer); GLenum usage; switch (hint) { case WRITE_EVERY_FRAME: usage = GL_STREAM_DRAW_ARB; break; case WRITE_ONCE: usage = GL_STATIC_DRAW_ARB; break; case WRITE_EVERY_FEW_FRAMES: usage = GL_DYNAMIC_DRAW_ARB; break; default: usage = GL_STREAM_DRAW_ARB; debugAssertM(false, "Fell through switch"); } // Load some (undefined) data to initialize the buffer glBufferDataARB(GL_ARRAY_BUFFER_ARB, size, NULL, usage); debugAssertGLOk(); // The basePointer is always NULL for a VBO basePointer = NULL; glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); //glPopClientAttrib(); debugAssertGLOk(); } break; case MAIN_MEMORY: // Use the base pointer glbuffer = 0; basePointer = malloc(size); debugAssert(basePointer); break; default: alwaysAssertM(false, "Fell through switch."); glbuffer = 0; basePointer = NULL; } milestone = NULL; allocated = 0; generation = 1; peakAllocated = 0; }
Model::Model(const std::string& filename, VARAreaRef varStatic) { // This loads an IFS file. Note that we could have used G3D::IFSModel::load to // parse the file for us. // file := // fileheader + // vertexheader + // vertex* + // triheader + // tri* // // fileheader := (string32) "IFS" + (float32)1.0 + (string32)modelname // vertexheader := (string32) "VERTICES" + (uint32)numVertices // vertex := (float32)x + (float32)y + (float32)z // triheader := (string32)"TRIANGLES" + (uint32)numFaces // tri := (uint32)v0 + (uint32)v1 + (uint32)v2 Log::common()->println(std::string("Loading ") + filename); BinaryInput b(filename, G3D_LITTLE_ENDIAN); std::string fmt = b.readString32(); float version = b.readFloat32(); (void) version; std::string name = b.readString32(); debugAssert(fmt == "IFS"); debugAssert(version == 1.0); std::string vertexHeader = b.readString32(); // Load the vertices vertex.resize(b.readUInt32()); for (int v = 0; v < vertex.size(); ++v) { vertex[v] = b.readVector3() * 5; } // Per-vertex normals normal.resize(vertex.size()); // Load the triangles std::string triHeader = b.readString32(); int numTris = b.readUInt32(); for (int t = 0; t < numTris; ++t) { int v0 = b.readUInt32(); int v1 = b.readUInt32(); int v2 = b.readUInt32(); // Compute the non-unit face normal Vector3 faceNormal = (vertex[v1] - vertex[v0]).cross( (vertex[v2] - vertex[v0])); normal[v0] += faceNormal; normal[v1] += faceNormal; normal[v2] += faceNormal; // Record the indices index.append(v0, v1, v2); } // Rescale the normals to unit length for (int n = 0; n < normal.size(); ++n) { normal[n] = normal[n].direction(); } varVertex = VAR(vertex, varStatic); varNormal = VAR(normal, varStatic); debugAssertGLOk(); }
void Demo::onGraphics(RenderDevice* rd) { rd->clear(sky == NULL, true, false); rd->setProjectionAndCameraMatrix(app->debugCamera); LightingParameters lighting(gameTime, false); if (sky.notNull()) { sky->render(rd, lighting); } rd->pushState(); // Setup lighting rd->setSpecularCoefficient(1); rd->setShininess(64); debugAssertGLOk(); rd->enableLighting(); rd->setLight(0, GLight::directional(lighting.lightDirection, lighting.lightColor)); rd->setLight(1, GLight::directional(-lighting.lightDirection, Color3::white() * .25, false)); rd->setAmbientLightColor(lighting.ambient); rd->setShadeMode(RenderDevice::SHADE_SMOOTH); static const Color3 color[] = {Color3::black(), Color3::white(), Color3::orange(), Color3::blue()}; double t[2]; Vector3 c[2]; t[0] = System::time(); t[1] = t[0] + 0.01; // Draw the planes for (int x = 0; x < N; ++x) { for (int i = 0; i < 2; ++i) { double a = x + t[i] + 2; double a2 = t[i] * (x + 1) * .01 + 1005.1; c[i] = Vector3(cos(a) * (10 + x / 2.0), sin(a2) * 10, sin(a) * 15); } CoordinateFrame cframe(c[0]); double a = t[0] * (x + 1) * .1; cframe.lookAt(c[1], Vector3(cos(a), 3, sin(a)).direction()); rd->setColor(color[x % 4]); model->render(rd, cframe, lighting, varStream); } rd->popState(); if (sky.notNull()) { sky->renderLensFlare(rd, lighting); } rd->push2D(); char* str = NULL; switch (renderMethod) { case TRIANGLES: str = "Using begin/end (SPACE to change)"; break; case VARSTREAM: str = "Using streaming vertex array (SPACE to change)"; break; case VARSTATIC: str = "Using static vertex array (SPACE to change)"; break; default:; } app->debugFont->draw2D(rd, str, Vector2(10, rd->height() - 40), 20, Color3::yellow(), Color3::black()); rd->pop2D(); debugAssertGLOk(); varStream->reset(); }
void Shader::ShaderProgram::compile (const Array<PreprocessedShaderSource>& pss, const String& preambleAndMacroArgs, const Args& args, const Table<int, String>& indexToNameTable, Array<String>& codeArray) { debugAssertGLOk(); codeArray.fastClear(); codeArray.resize(STAGE_COUNT); for (int s = 0; s < STAGE_COUNT; ++s) { const PreprocessedShaderSource& pSource = pss[s]; if (pSource.preprocessedCode != "") { String fullyProcessedCode = pSource.preprocessedCode; const bool processSuccess = Shader::expandForPragmas(fullyProcessedCode, args, indexToNameTable, messages); ok = ok && processSuccess; if (processSuccess) { String& code = codeArray[s] = pSource.versionString + pSource.extensionsString + preambleAndMacroArgs + pSource.g3dInsertString + fullyProcessedCode; GLint compiled = GL_FALSE; GLuint& glShader = glShaderObject[s]; glShader = glCreateShader(glShaderType(s)); // Compile the shader GLint length = (GLint)code.length(); // debugPrintf("Compiling a shader of %d kB\n", iRound(length / 1000.0f)); const GLchar* codePtr = static_cast<const GLchar*>(code.c_str()); int count = 1; glShaderSource(glShader, count, &codePtr, &length); glCompileShader(glShader); glGetShaderiv(glShader, GL_COMPILE_STATUS, &compiled); // Read the result of compilation GLint maxLength; glGetShaderiv(glShader, GL_INFO_LOG_LENGTH, &maxLength); debugAssertGLOk(); if (maxLength > 0) { GLchar* pInfoLog = (GLchar*)System::malloc(maxLength * sizeof(GLchar)); glGetShaderInfoLog(glShader, maxLength, &length, pInfoLog); readAndAppendShaderLog(pInfoLog, messages, pSource.filename, indexToNameTable); System::free(pInfoLog); } ok = ok && (compiled == GL_TRUE); # ifdef G3D_DEBUG if (! ok) { debugPrintf("Shader source:\n%s\n", codePtr); } # endif } } else { // No code to compile from, so the shader object does not exist glShaderObject[s] = 0; } } // for each stage }
std::string getOpenGLState(bool showDisabled) { { debugAssertGLOk(); glGetInteger(GL_BLEND); debugAssertM(glGetError() != GL_INVALID_OPERATION, "Can't call getOpenGLState between glBegin() and glEnd()"); } // The implementation has to be careful not to disrupt any OpenGL state and // to produce output code that sets values that interact (e.g. lighting and modelview matrix) in an order // so they produce the same results as currently in memory. std::string result; result += "///////////////////////////////////////////////////////////////////\n"; result += "// Matrices //\n\n"; result += getMatrixState(); result += "///////////////////////////////////////////////////////////////////\n"; result += "// Lighting //\n\n"; result += getLightingState(showDisabled); result += "///////////////////////////////////////////////////////////////////\n"; result += "// Clipping //\n\n"; result += getClippingState(); result += "///////////////////////////////////////////////////////////////////\n"; result += "// Textures //\n\n"; result += getTextureState(showDisabled); result += "///////////////////////////////////////////////////////////////////\n"; result += "// Other //\n\n"; GLdouble d[4]; GLboolean b[4]; // Viewport glGetDoublev(GL_VIEWPORT, d); result += format("glViewport(%g, %g, %g, %g);\n\n", d[0], d[1], d[2], d[3]); //color result += enableEntry(GL_COLOR_ARRAY); result += enableEntry(GL_COLOR_LOGIC_OP); result += enableEntry(GL_COLOR_MATERIAL); glGetDoublev(GL_COLOR_CLEAR_VALUE, d); result += format("glClearColor(%g, %g, %g, %g);\n", d[0], d[1], d[2], d[3]); glGetDoublev(GL_CURRENT_COLOR, d); result += format("glColor4d(%g, %g, %g, %g);\n", d[0], d[1], d[2], d[3]); glGetBooleanv(GL_COLOR_WRITEMASK, b); result += format("glColorMask(%d, %d, %d, %d);\n", b[0], b[1], b[2], b[3]); result += format("\n"); //blend result += enableEntry(GL_BLEND); if (showDisabled || glGetBoolean(GL_BLEND)) { result += format("glBlendFunc(%s, %s);\n", GLenumToString(glGetInteger(GL_BLEND_DST)), GLenumToString(glGetInteger(GL_BLEND_SRC))); result += format("\n"); } //alpha result += enableEntry(GL_ALPHA_TEST); if (showDisabled || glGetBoolean(GL_ALPHA_TEST)) { result += format("glAlphaFunc(%s, %g);\n", GLenumToString(glGetInteger(GL_ALPHA_TEST_FUNC)), glGetDouble(GL_ALPHA_TEST_REF)); result += format("\n"); } //depth stuff result += "///////////////////////////////////////////////////////////////////\n"; result += "// Depth Buffer //\n\n"; result += enableEntry(GL_DEPTH_TEST); if (showDisabled || glGetBoolean(GL_DEPTH_TEST)) { result += format("glDepthFunc(%s);\n", GLenumToString(glGetInteger(GL_DEPTH_FUNC))); } result += format("glClearDepth(%g);\n", glGetDouble(GL_DEPTH_CLEAR_VALUE)); result += format("glDepthMask(%d);\n", glGetBoolean(GL_DEPTH_WRITEMASK)); { Vector2 range = glGetVector2(GL_DEPTH_RANGE); result += format("glDepthRange(%g, %g);\n", range.x, range.y); } result += format("\n"); //stencil stuff result += "///////////////////////////////////////////////////////////////////////\n"; result += "// Stencil\n\n"; result += enableEntry(GL_STENCIL_TEST); result += format("glClearStencil(0x%x);\n", glGetInteger(GL_STENCIL_CLEAR_VALUE)); if (GLCaps::supports_GL_EXT_stencil_two_side()) { result += "glActiveStencilFaceEXT(GL_BACK);\n"; glActiveStencilFaceEXT(GL_BACK); } if (showDisabled || glGetBoolean(GL_STENCIL_TEST)) result += format( "glStencilFunc(%s, %d, %d);\n", GLenumToString(glGetInteger(GL_STENCIL_FUNC)), glGetInteger(GL_STENCIL_REF), glGetInteger(GL_STENCIL_VALUE_MASK)); result += format( "glStencilOp(%s, %s, %s);\n", GLenumToString(glGetInteger(GL_STENCIL_FAIL)), GLenumToString(glGetInteger(GL_STENCIL_PASS_DEPTH_FAIL)), GLenumToString(glGetInteger(GL_STENCIL_PASS_DEPTH_PASS))); result += format("glStencilMask(0x%x);\n", glGetInteger(GL_STENCIL_WRITEMASK)); if (GLCaps::supports_GL_EXT_stencil_two_side()) { result += "\nglActiveStencilFaceEXT(GL_FRONT);\n"; glActiveStencilFaceEXT(GL_FRONT); if (showDisabled || glGetBoolean(GL_STENCIL_TEST)) result += format( "glStencilFunc(%s, %d, %d);\n", GLenumToString(glGetInteger(GL_STENCIL_FUNC)), glGetInteger(GL_STENCIL_REF), glGetInteger(GL_STENCIL_VALUE_MASK)); result += format( "glStencilOp(%s, %s, %s);\n", GLenumToString(glGetInteger(GL_STENCIL_FAIL)), GLenumToString(glGetInteger(GL_STENCIL_PASS_DEPTH_FAIL)), GLenumToString(glGetInteger(GL_STENCIL_PASS_DEPTH_PASS))); result += format("glStencilMask(0x%x);\n", glGetInteger(GL_STENCIL_WRITEMASK)); } result += ("\n"); //misc result += enableEntry(GL_NORMAL_ARRAY); result += enableEntry(GL_NORMALIZE); glGetDoublev(GL_CURRENT_NORMAL, d); result += format("glNormal3d(%g, %g, %g);\n", d[0], d[1], d[2]); result += ("\n"); result += format("glPixelZoom(%g, %g);\n", glGetDouble(GL_ZOOM_X), glGetDouble(GL_ZOOM_Y)); result += format("glReadBuffer(%s);\n", GLenumToString(glGetInteger(GL_READ_BUFFER))); result += enableEntry(GL_POLYGON_SMOOTH); result += enableEntry(GL_POLYGON_STIPPLE); result += enableEntry(GL_LINE_SMOOTH); result += enableEntry(GL_LINE_STIPPLE); result += enableEntry(GL_POINT_SMOOTH); result += enableEntry(GL_AUTO_NORMAL); result += enableEntry(GL_CULL_FACE); result += enableEntry(GL_POLYGON_OFFSET_FILL); result += enableEntry(GL_POLYGON_OFFSET_LINE); result += enableEntry(GL_POLYGON_OFFSET_POINT); result += ("\n"); result += enableEntry(GL_DITHER); result += enableEntry(GL_FOG); result += enableEntry(GL_VERTEX_ARRAY); result += enableEntry(GL_INDEX_ARRAY); result += enableEntry(GL_INDEX_LOGIC_OP); result += format("\n"); result += enableEntry(GL_MAP1_COLOR_4); result += enableEntry(GL_MAP1_INDEX); result += enableEntry(GL_MAP1_NORMAL); result += enableEntry(GL_MAP1_TEXTURE_COORD_1); result += enableEntry(GL_MAP1_TEXTURE_COORD_2); result += enableEntry(GL_MAP1_TEXTURE_COORD_3); result += enableEntry(GL_MAP1_TEXTURE_COORD_4); result += enableEntry(GL_MAP1_VERTEX_3); result += enableEntry(GL_MAP1_VERTEX_4); result += enableEntry(GL_MAP2_COLOR_4); result += enableEntry(GL_MAP2_INDEX); result += enableEntry(GL_MAP2_NORMAL); result += enableEntry(GL_MAP2_TEXTURE_COORD_1); result += enableEntry(GL_MAP2_TEXTURE_COORD_2); result += enableEntry(GL_MAP2_TEXTURE_COORD_3); result += enableEntry(GL_MAP2_TEXTURE_COORD_4); result += enableEntry(GL_MAP2_VERTEX_3); result += enableEntry(GL_MAP2_VERTEX_4); result += format("\n"); result += enableEntry(GL_SCISSOR_TEST); return result; }
void Shader::ShaderProgram::addActiveUniformsFromProgram() { // Length of the longest variable name GLint maxLength; // Number of uniform variables GLint uniformCount; // Get the number of uniforms, and the length of the longest name. glGetProgramiv(glShaderProgramObject(), GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLength); glGetProgramiv(glShaderProgramObject(), GL_ACTIVE_UNIFORMS, &uniformCount); GLchar* name = (GLchar *) malloc(maxLength * sizeof(GLchar)); // Get the sizes, types and names int lastTextureUnit = -1; int lastImageUnit = -1; // Loop over glGetActiveUniform and store the results away. for (int i = 0; i < uniformCount; ++i) { const GLuint uniformIndex = i; GLuint programObject = glShaderProgramObject(); GLint elementNum; GLenum type; glGetActiveUniform(programObject, uniformIndex, maxLength, NULL, &elementNum, &type, name); UniformDeclaration& d = uniformDeclarationTable.getCreate(name); d.name = name; d.location = glGetUniformLocation(glShaderProgramObject(), name); d.type = type; d.elementNum = elementNum; bool isGLBuiltIn = (d.location == -1) || ((strlen(name) > 3) && beginsWith(String(name), "gl_")); d.dummy = isGLBuiltIn; d.index = -1; if (! isGLBuiltIn) { if (isSamplerType(d.type)) { ++lastTextureUnit; d.glUnit = lastTextureUnit; } else if (isImageType(d.type)) { ++lastImageUnit; d.glUnit = lastImageUnit; } else if (d.elementNum == 1) { // Not array d.glUnit = -1; } else { // Is an array, remove from uniform declaration table, and add it's elements GLint type = d.type; int arraySize = (int)d.elementNum; int glUnit = -1; uniformDeclarationTable.remove(name); // Get rid of [0] if it exists (depends on driver) String arrayName = name; if (arrayName[arrayName.length()-1] == ']') { size_t bracketLoc = arrayName.rfind('['); // TODO: error handle if "[" doesn't exist arrayName = arrayName.substr(0, bracketLoc); } for (int i = 0; i < arraySize; ++i) { const String appendedName = format("%s[%d]", arrayName.c_str(), i); UniformDeclaration& elementDeclaration = uniformDeclarationTable.getCreate(appendedName); GLint location = glGetUniformLocation(glShaderProgramObject(), appendedName.c_str()); debugAssertGLOk(); bool dummy = (location == -1); elementDeclaration.setAllFields(appendedName, i, type, location, dummy, glUnit); } } } } free(name); }