const char* PezInitialize(int width, int height) { BuddhaMesh = CreateMesh("buddha.ctm"); QuadVbo = CreateQuad(-1, -1, 1, 1); #ifdef LIGHTING DepthProgram = CreateProgram("Glass.Vertex", "Glass.Fragment.Lighting" SUFFIX); AbsorptionProgram = CreateProgram("Glass.Vertex.Quad", "Glass.Fragment.Blit" SUFFIX); #else DepthProgram = CreateProgram("Glass.Vertex", "Glass.Fragment.Depth" SUFFIX); AbsorptionProgram = CreateProgram("Glass.Vertex.Quad", "Glass.Fragment.Absorption" SUFFIX); #endif // Create a floating-point render target: GLuint textureHandle; glGenTextures(1, &textureHandle); glBindTexture(GL_TEXTURE_2D, textureHandle); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); #ifdef LIGHTING glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 768, 1024, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); #elif defined(__IPAD__) glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 768, 1024, 0, GL_LUMINANCE, GL_HALF_FLOAT_OES, 0); #else glTexImage2D(GL_TEXTURE_2D, 0, GL_RG16F, 768, 1024, 0, GL_RG, GL_FLOAT, 0); #endif PezCheckCondition(GL_NO_ERROR == glGetError(), "This passes on Mac OS X and iOS."); OffscreenTexture = textureHandle; GLuint fboHandle; glGenFramebuffers(1, &fboHandle); glBindFramebuffer(GL_FRAMEBUFFER, fboHandle); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureHandle, 0); #ifdef LIGHTING GLuint depthRenderbuffer; glGenRenderbuffers(1, &depthRenderbuffer); glBindRenderbuffer(GL_RENDERBUFFER, depthRenderbuffer); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthRenderbuffer); #endif PezCheckCondition(GL_FRAMEBUFFER_COMPLETE == glCheckFramebufferStatus(GL_FRAMEBUFFER), "This asserts on iOS and passes on Mac OS X."); OffscreenFbo = fboHandle; glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindRenderbuffer(GL_RENDERBUFFER, 0); // Set up the projection matrix: const float HalfWidth = 0.5; const float HalfHeight = HalfWidth * PEZ_VIEWPORT_HEIGHT / PEZ_VIEWPORT_WIDTH; ProjectionMatrix = M4MakeFrustum(-HalfWidth, +HalfWidth, -HalfHeight, +HalfHeight, 5, 20); return "Glass Demo"; }
GLuint CreateProgram(const char* vsKey, const char* fsKey) { static int first = 1; if (first) { glswInit(); glswAddPath("../", ".glsl"); glswAddPath("./", ".glsl"); char qualifiedPath[128]; strcpy(qualifiedPath, PezResourcePath()); strcat(qualifiedPath, "/"); glswAddPath(qualifiedPath, ".glsl"); first = 0; } const char* vsSource = glswGetShader(vsKey); const char* fsSource = glswGetShader(fsKey); const char* msg = "Can't find %s shader: '%s'.\n"; PezCheckCondition(vsSource != 0, msg, "vertex", vsKey); PezCheckCondition(fsSource != 0, msg, "fragment", fsKey); GLint compileSuccess; GLchar compilerSpew[256]; GLuint vsHandle = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vsHandle, 1, &vsSource, 0); glCompileShader(vsHandle); glGetShaderiv(vsHandle, GL_COMPILE_STATUS, &compileSuccess); glGetShaderInfoLog(vsHandle, sizeof(compilerSpew), 0, compilerSpew); PezCheckCondition(compileSuccess, "Can't compile %s:\n%s", vsKey, compilerSpew); GLuint fsHandle = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fsHandle, 1, &fsSource, 0); glCompileShader(fsHandle); glGetShaderiv(fsHandle, GL_COMPILE_STATUS, &compileSuccess); glGetShaderInfoLog(fsHandle, sizeof(compilerSpew), 0, compilerSpew); PezCheckCondition(compileSuccess, "Can't compile %s:\n%s", fsKey, compilerSpew); GLuint programHandle = glCreateProgram(); glAttachShader(programHandle, vsHandle); glAttachShader(programHandle, fsHandle); glLinkProgram(programHandle); GLint linkSuccess; glGetProgramiv(programHandle, GL_LINK_STATUS, &linkSuccess); glGetProgramInfoLog(programHandle, sizeof(compilerSpew), 0, compilerSpew); PezCheckCondition(linkSuccess, "Can't link %s with %s:\n%s", vsKey, fsKey, compilerSpew); return programHandle; }
Surface CreateSurface(GLsizei width, GLsizei height, int numComponents) { GLuint fboHandle; glGenFramebuffers(1, &fboHandle); glBindFramebuffer(GL_FRAMEBUFFER, fboHandle); GLuint textureHandle; glGenTextures(1, &textureHandle); glBindTexture(GL_TEXTURE_2D, textureHandle); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); const int UseHalfFloats = 1; if (UseHalfFloats) { switch (numComponents) { case 1: glTexImage2D(GL_TEXTURE_2D, 0, GL_R16F, width, height, 0, GL_RED, GL_HALF_FLOAT, 0); break; case 2: glTexImage2D(GL_TEXTURE_2D, 0, GL_RG16F, width, height, 0, GL_RG, GL_HALF_FLOAT, 0); break; case 3: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, width, height, 0, GL_RGB, GL_HALF_FLOAT, 0); break; case 4: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, GL_HALF_FLOAT, 0); break; default: PezFatalError("Illegal slab format."); } } else { switch (numComponents) { case 1: glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, width, height, 0, GL_RED, GL_FLOAT, 0); break; case 2: glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32F, width, height, 0, GL_RG, GL_FLOAT, 0); break; case 3: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, width, height, 0, GL_RGB, GL_FLOAT, 0); break; case 4: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, 0); break; default: PezFatalError("Illegal slab format."); } } PezCheckCondition(GL_NO_ERROR == glGetError(), "Unable to create normals texture"); GLuint colorbuffer; glGenRenderbuffers(1, &colorbuffer); glBindRenderbuffer(GL_RENDERBUFFER, colorbuffer); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureHandle, 0); PezCheckCondition(GL_NO_ERROR == glGetError(), "Unable to attach color buffer"); PezCheckCondition(GL_FRAMEBUFFER_COMPLETE == glCheckFramebufferStatus(GL_FRAMEBUFFER), "Unable to create FBO."); Surface surface = { fboHandle, textureHandle, numComponents }; glClearColor(0, 0, 0, 0); glClear(GL_COLOR_BUFFER_BIT); glBindFramebuffer(GL_FRAMEBUFFER, 0); return surface; }
static void LoadEffect() { const char* vsSource, * fsSource; GLuint vsHandle, fsHandle; GLint compileSuccess, linkSuccess; GLchar compilerSpew[256]; GLuint programHandle; glswInit(); glswSetPath("../demo/", ".glsl"); glswAddDirectiveToken("GL3", "#version 130"); vsSource = glswGetShader("Simple.Vertex.Textured." PEZ_GL_VERSION_TOKEN); fsSource = glswGetShader("Simple.Fragment.Textured." PEZ_GL_VERSION_TOKEN); PezCheckCondition(vsSource, "Can't find vertex shader.\n"); PezCheckCondition(fsSource, "Can't find fragment shader.\n"); vsHandle = glCreateShader(GL_VERTEX_SHADER); fsHandle = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(vsHandle, 1, &vsSource, 0); glCompileShader(vsHandle); glGetShaderiv(vsHandle, GL_COMPILE_STATUS, &compileSuccess); glGetShaderInfoLog(vsHandle, sizeof(compilerSpew), 0, compilerSpew); PezCheckCondition(compileSuccess, compilerSpew); glShaderSource(fsHandle, 1, &fsSource, 0); glCompileShader(fsHandle); glGetShaderiv(fsHandle, GL_COMPILE_STATUS, &compileSuccess); glGetShaderInfoLog(fsHandle, sizeof(compilerSpew), 0, compilerSpew); PezCheckCondition(compileSuccess, compilerSpew); programHandle = glCreateProgram(); glAttachShader(programHandle, vsHandle); glAttachShader(programHandle, fsHandle); glBindAttribLocation(programHandle, PositionSlot, "Position"); glBindAttribLocation(programHandle, TexCoordSlot, "InCoord"); glLinkProgram(programHandle); glGetProgramiv(programHandle, GL_LINK_STATUS, &linkSuccess); glGetProgramInfoLog(programHandle, sizeof(compilerSpew), 0, compilerSpew); PezCheckCondition(linkSuccess, compilerSpew); glUseProgram(programHandle); }
INT WINAPI WinMain(HINSTANCE hInst, HINSTANCE ignoreMe0, LPSTR ignoreMe1, INT ignoreMe2) { LPCSTR szName = "Pez App"; WNDCLASSEXA wc = { sizeof(WNDCLASSEX), CS_CLASSDC | CS_DBLCLKS, MsgProc, 0L, 0L, GetModuleHandle(0), 0, 0, 0, 0, szName, 0 }; DWORD dwStyle = WS_SYSMENU | WS_VISIBLE | WS_POPUP; DWORD dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; RECT rect; int windowWidth, windowHeight, windowLeft, windowTop; HWND hWnd; PIXELFORMATDESCRIPTOR pfd; HDC hDC; HGLRC hRC; int pixelFormat; GLenum err; MSG msg = {0}; LARGE_INTEGER previousTime; LARGE_INTEGER freqTime; wc.hCursor = LoadCursor(0, IDC_ARROW); RegisterClassExA(&wc); SetRect(&rect, 0, 0, PEZ_VIEWPORT_WIDTH, PEZ_VIEWPORT_HEIGHT); AdjustWindowRectEx(&rect, dwStyle, FALSE, dwExStyle); windowWidth = rect.right - rect.left; windowHeight = rect.bottom - rect.top; windowLeft = GetSystemMetrics(SM_XVIRTUALSCREEN) + GetSystemMetrics(SM_CXSCREEN) / 2 - windowWidth / 2; windowTop = GetSystemMetrics(SM_CYSCREEN) / 2 - windowHeight / 2; hWnd = CreateWindowExA(0, szName, szName, dwStyle, windowLeft, windowTop, windowWidth, windowHeight, 0, 0, 0, 0); // Create the GL context. ZeroMemory(&pfd, sizeof(pfd)); pfd.nSize = sizeof(pfd); pfd.nVersion = 1; pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; pfd.iPixelType = PFD_TYPE_RGBA; pfd.cColorBits = 24; pfd.cDepthBits = 0; pfd.cStencilBits = 0; pfd.iLayerType = PFD_MAIN_PLANE; hDC = GetDC(hWnd); pixelFormat = ChoosePixelFormat(hDC, &pfd); SetPixelFormat(hDC, pixelFormat, &pfd); hRC = wglCreateContext(hDC); wglMakeCurrent(hDC, hRC); if (PEZ_ENABLE_MULTISAMPLING) { int pixelAttribs[] = { WGL_SAMPLES_ARB, 16, WGL_SAMPLE_BUFFERS_ARB, GL_TRUE, WGL_DRAW_TO_WINDOW_ARB, GL_TRUE, WGL_SUPPORT_OPENGL_ARB, GL_TRUE, WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB, WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB, WGL_RED_BITS_ARB, 8, WGL_GREEN_BITS_ARB, 8, WGL_BLUE_BITS_ARB, 8, WGL_ALPHA_BITS_ARB, 8, WGL_DEPTH_BITS_ARB, 24, WGL_STENCIL_BITS_ARB, 8, WGL_DOUBLE_BUFFER_ARB, GL_TRUE, 0 }; int* sampleCount = pixelAttribs + 1; int* useSampleBuffer = pixelAttribs + 3; int pixelFormat = -1; PROC proc = wglGetProcAddress("wglChoosePixelFormatARB"); unsigned int numFormats; PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC) proc; if (!wglChoosePixelFormatARB) { PezFatalError("Could not load function pointer for 'wglChoosePixelFormatARB'. Is your driver properly installed?"); } // Try fewer and fewer samples per pixel till we find one that is supported: while (pixelFormat <= 0 && *sampleCount >= 0) { wglChoosePixelFormatARB(hDC, pixelAttribs, 0, 1, &pixelFormat, &numFormats); (*sampleCount)--; if (*sampleCount <= 1) { *useSampleBuffer = GL_FALSE; } } // Win32 allows the pixel format to be set only once per app, so destroy and re-create the app: DestroyWindow(hWnd); hWnd = CreateWindowExA(0, szName, szName, dwStyle, windowLeft, windowTop, windowWidth, windowHeight, 0, 0, 0, 0); SetWindowPos(hWnd, HWND_TOP, windowLeft, windowTop, windowWidth, windowHeight, 0); hDC = GetDC(hWnd); SetPixelFormat(hDC, pixelFormat, &pfd); hRC = wglCreateContext(hDC); wglMakeCurrent(hDC, hRC); } #define PEZ_TRANSPARENT_WINDOW 0 // For transparency, this doesn't seem to work. I think I'd need to read back from an OpenGL FBO and blit it with GDI. if (PEZ_TRANSPARENT_WINDOW) { long flag = GetWindowLong(hWnd, GWL_EXSTYLE); int opacity = 128; flag |= WS_EX_LAYERED; SetWindowLong(hWnd, GWL_EXSTYLE, flag); SetLayeredWindowAttributes(hWnd, 0, opacity, LWA_ALPHA); } err = glewInit(); if (GLEW_OK != err) { PezFatalError("GLEW Error: %s\n", glewGetErrorString(err)); } PezDebugString("OpenGL Version: %s\n", glGetString(GL_VERSION)); if (!PEZ_VERTICAL_SYNC) { wglSwapIntervalEXT(0); } if (PEZ_FORWARD_COMPATIBLE_GL) { const int contextAttribs[] = { WGL_CONTEXT_MAJOR_VERSION_ARB, 3, WGL_CONTEXT_MINOR_VERSION_ARB, 2, WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, 0 }; HGLRC newRC = wglCreateContextAttribsARB(hDC, 0, contextAttribs); wglMakeCurrent(0, 0); wglDeleteContext(hRC); hRC = newRC; wglMakeCurrent(hDC, hRC); } { const char* szWindowTitle = PezInitialize(PEZ_VIEWPORT_WIDTH, PEZ_VIEWPORT_HEIGHT); SetWindowTextA(hWnd, szWindowTitle); } QueryPerformanceFrequency(&freqTime); QueryPerformanceCounter(&previousTime); // ------------------- // Start the Game Loop // ------------------- while (msg.message != WM_QUIT) { if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } else { LARGE_INTEGER currentTime; __int64 elapsed; double deltaTime; QueryPerformanceCounter(¤tTime); elapsed = currentTime.QuadPart - previousTime.QuadPart; deltaTime = elapsed * 1000000.0 / freqTime.QuadPart; previousTime = currentTime; PezUpdate((unsigned int) deltaTime); PezRender(0); SwapBuffers(hDC); PezCheckCondition(glGetError() == GL_NO_ERROR, "OpenGL error.\n"); } } UnregisterClassA(szName, wc.hInstance); return 0; }
Mesh CreateMesh(const char* ctmFile, float totalScale, float lengthScale) { Mesh mesh = {0}; char qualifiedPath[256] = {0}; strcpy(qualifiedPath, PezResourcePath()); strcat(qualifiedPath, "/\0"); strcat(qualifiedPath, ctmFile); // Open the CTM file: CTMcontext ctmContext = ctmNewContext(CTM_IMPORT); ctmLoad(ctmContext, qualifiedPath); PezCheckCondition(ctmGetError(ctmContext) == CTM_NONE, "OpenCTM issue with loading %s", qualifiedPath); CTMuint vertexCount = ctmGetInteger(ctmContext, CTM_VERTEX_COUNT); CTMuint faceCount = ctmGetInteger(ctmContext, CTM_TRIANGLE_COUNT); // Create the VBO for positions: const CTMfloat* positions = ctmGetFloatArray(ctmContext, CTM_VERTICES); if (positions) { // Find bounding box float m = 99999.0f; Point3 minCorner = P3MakeFromElems(m, m, m); Point3 maxCorner = P3MakeFromElems(-m, -m, -m); const CTMfloat* pSrc = positions; CTMuint remainingVerts = vertexCount; while (remainingVerts--) { float x = *pSrc++; float y = *pSrc++; float z = *pSrc++; Point3 p = P3MakeFromElems(x, y, z); minCorner = P3MinPerElem(p, minCorner); maxCorner = P3MaxPerElem(p, maxCorner); } // Scale such that the Z extent is 'scale' // The X and Y scales are computed according to the aspect ratio. // The model is centered at (+0.5, +0.5, +0.5). float xratio = (maxCorner.x - minCorner.x) / (maxCorner.z - minCorner.z); float yratio = (maxCorner.y - minCorner.y) / (maxCorner.z - minCorner.z); float sx = lengthScale * totalScale * xratio / (maxCorner.x - minCorner.x); float sy = totalScale * yratio / (maxCorner.y - minCorner.y); float sz = totalScale / (maxCorner.z - minCorner.z); pSrc = positions; remainingVerts = vertexCount; CTMfloat* pDest = (CTMfloat*) positions; while (remainingVerts--) { float x = *pSrc++; float y = *pSrc++; float z = *pSrc++; *pDest++ = (x - minCorner.x) * sx - totalScale * xratio / 2; *pDest++ = (y - minCorner.y) * sy - totalScale * yratio / 2; *pDest++ = (z - minCorner.z) * sz - totalScale / 2; } GLuint handle; GLsizeiptr size = vertexCount * sizeof(float) * 3; glGenBuffers(1, &handle); glBindBuffer(GL_ARRAY_BUFFER, handle); glBufferData(GL_ARRAY_BUFFER, size, positions, GL_STATIC_DRAW); mesh.Positions = handle; } // Create the VBO for normals: const CTMfloat* normals = ctmGetFloatArray(ctmContext, CTM_NORMALS); if (normals) { GLuint handle; GLsizeiptr size = vertexCount * sizeof(float) * 3; glGenBuffers(1, &handle); glBindBuffer(GL_ARRAY_BUFFER, handle); glBufferData(GL_ARRAY_BUFFER, size, normals, GL_STATIC_DRAW); mesh.Normals = handle; } // Create the VBO for indices: const CTMuint* indices = ctmGetIntegerArray(ctmContext, CTM_INDICES); if (indices) { GLsizeiptr bufferSize = faceCount * 3 * sizeof(GLuint); GLuint handle; glGenBuffers(1, &handle); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, handle); glBufferData(GL_ELEMENT_ARRAY_BUFFER, bufferSize, indices, GL_STATIC_DRAW); mesh.Faces = handle; } ctmFreeContext(ctmContext); mesh.FaceCount = faceCount; mesh.VertexCount = vertexCount; glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); return mesh; }
Mesh CreateMesh(const char* ctmFile) { Mesh mesh = {0, 0, 0, 0}; char qualifiedPath[256] = {0}; strcpy(qualifiedPath, PezResourcePath()); strcat(qualifiedPath, "/\0"); strcat(qualifiedPath, ctmFile); // Open the CTM file: CTMcontext ctmContext = ctmNewContext(CTM_IMPORT); ctmLoad(ctmContext, qualifiedPath); PezCheckCondition(ctmGetError(ctmContext) == CTM_NONE, "OpenCTM issue with loading %s", qualifiedPath); CTMuint vertexCount = ctmGetInteger(ctmContext, CTM_VERTEX_COUNT); CTMuint faceCount = ctmGetInteger(ctmContext, CTM_TRIANGLE_COUNT); // Create the VBO for positions: const CTMfloat* positions = ctmGetFloatArray(ctmContext, CTM_VERTICES); if (positions) { GLuint handle; GLsizeiptr size = vertexCount * sizeof(float) * 3; glGenBuffers(1, &handle); glBindBuffer(GL_ARRAY_BUFFER, handle); glBufferData(GL_ARRAY_BUFFER, size, positions, GL_STATIC_DRAW); mesh.Positions = handle; } // Create the VBO for normals: const CTMfloat* normals = ctmGetFloatArray(ctmContext, CTM_NORMALS); if (normals) { GLuint handle; GLsizeiptr size = vertexCount * sizeof(float) * 3; glGenBuffers(1, &handle); glBindBuffer(GL_ARRAY_BUFFER, handle); glBufferData(GL_ARRAY_BUFFER, size, normals, GL_STATIC_DRAW); mesh.Normals = handle; } // Create the VBO for indices: const CTMuint* indices = ctmGetIntegerArray(ctmContext, CTM_INDICES); if (indices) { GLsizeiptr bufferSize = faceCount * 3 * sizeof(unsigned short); // Convert indices from 32-bit to 16-bit: unsigned short* faceBuffer = (unsigned short*) malloc(bufferSize); unsigned short* pDest = faceBuffer; const CTMuint* pSrc = indices; unsigned int remainingFaces = faceCount; while (remainingFaces--) { *pDest++ = (unsigned short) *pSrc++; *pDest++ = (unsigned short) *pSrc++; *pDest++ = (unsigned short) *pSrc++; } GLuint handle; glGenBuffers(1, &handle); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, handle); glBufferData(GL_ELEMENT_ARRAY_BUFFER, bufferSize, faceBuffer, GL_STATIC_DRAW); mesh.Faces = handle; free(faceBuffer); } ctmFreeContext(ctmContext); mesh.FaceCount = faceCount; glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); return mesh; }
GLuint CreateProgram(const char* vsKey, const char* gsKey, const char* fsKey) { static int first = 1; if (first) { glswInit(); glswAddPath("../", ".glsl"); glswAddPath("./", ".glsl"); char qualifiedPath[128]; strcpy(qualifiedPath, PezResourcePath()); strcat(qualifiedPath, "/"); glswAddPath(qualifiedPath, ".glsl"); glswAddDirective("*", "#version 150"); first = 0; } const char* vsSource = glswGetShader(vsKey); const char* gsSource = glswGetShader(gsKey); const char* fsSource = glswGetShader(fsKey); const char* msg = "Can't find %s shader: '%s'.\n"; PezCheckCondition(vsSource != 0, msg, "vertex", vsKey); PezCheckCondition(gsKey == 0 || gsSource != 0, msg, "geometry", gsKey); PezCheckCondition(fsKey == 0 || fsSource != 0, msg, "fragment", fsKey); GLint compileSuccess; GLchar compilerSpew[256]; GLuint programHandle = glCreateProgram(); GLuint vsHandle = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vsHandle, 1, &vsSource, 0); glCompileShader(vsHandle); glGetShaderiv(vsHandle, GL_COMPILE_STATUS, &compileSuccess); glGetShaderInfoLog(vsHandle, sizeof(compilerSpew), 0, compilerSpew); PezCheckCondition(compileSuccess, "Can't compile %s:\n%s", vsKey, compilerSpew); glAttachShader(programHandle, vsHandle); GLuint gsHandle; if (gsKey) { gsHandle = glCreateShader(GL_GEOMETRY_SHADER); glShaderSource(gsHandle, 1, &gsSource, 0); glCompileShader(gsHandle); glGetShaderiv(gsHandle, GL_COMPILE_STATUS, &compileSuccess); glGetShaderInfoLog(gsHandle, sizeof(compilerSpew), 0, compilerSpew); PezCheckCondition(compileSuccess, "Can't compile %s:\n%s", gsKey, compilerSpew); glAttachShader(programHandle, gsHandle); } GLuint fsHandle; if (fsKey) { fsHandle = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fsHandle, 1, &fsSource, 0); glCompileShader(fsHandle); glGetShaderiv(fsHandle, GL_COMPILE_STATUS, &compileSuccess); glGetShaderInfoLog(fsHandle, sizeof(compilerSpew), 0, compilerSpew); PezCheckCondition(compileSuccess, "Can't compile %s:\n%s", fsKey, compilerSpew); glAttachShader(programHandle, fsHandle); } glLinkProgram(programHandle); GLint linkSuccess; glGetProgramiv(programHandle, GL_LINK_STATUS, &linkSuccess); glGetProgramInfoLog(programHandle, sizeof(compilerSpew), 0, compilerSpew); if (!linkSuccess) { PezDebugString("Link error.\n"); if (vsKey) PezDebugString("Vertex Shader: %s\n", vsKey); if (gsKey) PezDebugString("Geometry Shader: %s\n", gsKey); if (fsKey) PezDebugString("Fragment Shader: %s\n", fsKey); PezDebugString("%s\n", compilerSpew); } return programHandle; }
void setup() { // 3. Define and compile vertex and fragment shaders GLuint vs; GLuint fs; GLint compileSuccess, linkSuccess; GLchar compilerSpew[256]; glswInit(); glswSetPath("../shader/", ".glsl"); glswAddDirectiveToken("GL3", "#version 150"); const char *vss = glswGetShader("test.Vertex.GL3"); const char *fss = glswGetShader("test.Fragment.GL3"); PezCheckCondition((void *)vss, "Can't find vertex shader.\n"); PezCheckCondition((void *)fss, "Can't find fragment shader.\n"); vs = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vs, 1, &vss, NULL); glCompileShader(vs); glGetShaderiv(vs, GL_COMPILE_STATUS, &compileSuccess); glGetShaderInfoLog(vs, sizeof(compilerSpew), 0, compilerSpew); PezCheckCondition((void*)compileSuccess, compilerSpew); fs = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fs, 1, &fss, NULL); glCompileShader(fs); glGetShaderiv(fs, GL_COMPILE_STATUS, &compileSuccess); glGetShaderInfoLog(fs, sizeof(compilerSpew), 0, compilerSpew); PezCheckCondition((void*)compileSuccess, compilerSpew); shaderProgram = glCreateProgram(); glAttachShader(shaderProgram, vs); glAttachShader(shaderProgram, fs); glBindFragDataLocation(shaderProgram, 0, "fragColour"); glLinkProgram(shaderProgram); glGetProgramiv(shaderProgram, GL_LINK_STATUS, &linkSuccess); glGetProgramInfoLog(shaderProgram, sizeof(compilerSpew), 0, compilerSpew); PezCheckCondition((void*)linkSuccess, compilerSpew); positionUniform = glGetUniformLocation(shaderProgram, "p"); colourAttribute = glGetAttribLocation(shaderProgram, "colour"); positionAttribute = glGetAttribLocation(shaderProgram, "position"); glDeleteShader(vs); glDeleteShader(fs); GLfloat vertexData[]= { -0.5,-0.5,0.0,1.0, 1.0,0.0,0.0,1.0, -0.5, 0.5,0.0,1.0, 0.0,1.0,0.0,1.0, 0.5, 0.5,0.0,1.0, 0.0,0.0,1.0,1.0, 0.5,-0.5,0.0,1.0, 1.0,1.0,1.0,1.0}; glGenVertexArrays(1, &vertexArrayObject); glBindVertexArray(vertexArrayObject); glGenBuffers(1, &vertexBuffer); glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); glBufferData(GL_ARRAY_BUFFER, 4*8*sizeof(GLfloat), vertexData, GL_STATIC_DRAW); glEnableVertexAttribArray((GLuint)positionAttribute); glEnableVertexAttribArray((GLuint)colourAttribute ); glVertexAttribPointer((GLuint)positionAttribute, 4, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), 0); glVertexAttribPointer((GLuint)colourAttribute , 4, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), (char*)0+4*sizeof(GLfloat)); }