Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //--------------------------------------------------------------------------------------
- // BTH - Stefan Petersson 2014.
- // - updated by FLL
- //--------------------------------------------------------------------------------------
- #include <windows.h>
- #include <string>
- #include <fstream>
- #include <streambuf>
- #define GLM_ENABLE_EXPERIMENTAL
- #include "imgui/imgui.h"
- #include "imgui/imgui_impl_win32.h"
- #include "imgui/imgui_impl_opengl3.h"
- #include "glm/glm.hpp"
- #include "glm/ext.hpp"
- #include "glm/gtc/matrix_transform.hpp"
- #include "glm/gtx/transform.hpp"
- #include <gl/glew.h>
- #include <gl/GL.h>
- #define STB_IMAGE_IMPLEMENTATION
- #include "bth_image.h"
- #pragma comment(lib, "opengl32.lib")
- #pragma comment(lib, "glew32.lib")
- #define WIDTH 1024
- #define HEIGHT 768
- using namespace std;
- HWND InitWindow(HINSTANCE hInstance);
- LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
- HGLRC CreateOpenGLContext(HWND wndHandle);
- // OpenGL uses unsigned integers to keep track of
- // created resources (shaders, vertices, textures, etc)
- // For simplicity, we make them global here, but it is
- // safe to put them in a class and pass around...
- GLuint gVertexBuffer = 0;
- GLuint gVertexAttribute = 0;
- GLuint gShaderProgram = 0;
- GLuint bth_tex;
- float gFloat = 0;
- float gClearColour[3] {};
- float gUniformColour[3] {};
- GLint gUniformColourLoc = -1;
- float gOffsetX = 0.0f;
- float gIncrement = 0.0f;
- //const unsigned int BTH_IMAGE_WIDTH = 64;
- //const unsigned int BTH_IMAGE_HEIGHT = 64;
- //unsigned char BTH_IMAGE_DATA[] = { 0 };
- glm::mat4 WorldMatrix;
- glm::mat4 ViewMatrix;
- glm::mat4 ProjectionMatrix;
- // macro that returns "char*" with offset "i"
- // BUFFER_OFFSET(5) transforms in "(char*)nullptr+(5)"
- #define BUFFER_OFFSET(i) ((char *)nullptr + (i))
- void CreateTexture() {
- glGenTextures(1, &bth_tex);
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, bth_tex);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, WIDTH, HEIGHT, 0, GL_RGBA,GL_UNSIGNED_BYTE, BTH_IMAGE_DATA);
- }
- void createMatrix(float time) {
- glm::mat4 scaleMatrix = glm::scale(glm::mat4(1.0f), glm::vec3(1.0f, 1.0f, 1.0f));
- //glm::mat4 rotationMatrix = glm::rotate(glm::mat4(1.0f), 3.14f, glm::vec3(1.0));
- glm::mat4 rotationMatrix = glm::rotate(scaleMatrix, 0.05f * time, glm::vec3(0, 1, 0));
- WorldMatrix = scaleMatrix * rotationMatrix;
- ProjectionMatrix = glm::perspective(
- glm::radians(3.14f*0.45f), // The vertical Field of View, in radians: the amount of "zoom". Think "camera lens". Usually between 90° (extra wide) and 30° (quite zoomed in)
- (float)WIDTH / (float)HEIGHT, // Aspect Ratio. Depends on the size§ of your window. Notice that 4/3 == 800/600 == 1280/960, sounds familiar ?
- 0.1f, // Near clipping plane. Keep as big as possible, or you'll get precision issues.
- 20.0f // Far clipping plane. Keep as little as possible.
- );
- glm::mat4 Projection = glm::perspective(3.14f * 0.45f, (float)WIDTH / (float)HEIGHT, 0.1f, 20.0f);
- glm::mat4 View = glm::lookAt(
- glm::vec3(0, 0, -2), // Camera is at (4,3,3), in World Space
- glm::vec3(0, 0, 0), // and looks at the origin
- glm::vec3(0, 1, 0) // Head is up (set to 0,-1,0 to look upside-down)
- );
- WorldMatrix = Projection * View * WorldMatrix; // projectionMatrix * ViewMatrix * worldMatrix;
- }
- void CreateShaders()
- {
- // local buffer to store error strings when compiling.
- char buff[1024];
- memset(buff, 0, 1024);
- GLint compileResult = 0;
- //create vertex shader "name" and store it in "vs"
- GLuint vs = glCreateShader(GL_VERTEX_SHADER);
- // open .glsl file and put it in a string
- ifstream shaderFile("VertexShader.glsl");
- std::string shaderText((std::istreambuf_iterator<char>(shaderFile)), std::istreambuf_iterator<char>());
- shaderFile.close();
- // glShaderSource requires a double pointer.
- // get the pointer to the c style string stored in the string object.
- const char* shaderTextPtr = shaderText.c_str();
- // ask GL to use this string a shader code source
- glShaderSource(vs, 1, &shaderTextPtr, nullptr);
- // try to compile this shader source.
- glCompileShader(vs);
- // check for compilation error
- glGetShaderiv(vs, GL_COMPILE_STATUS, &compileResult);
- if (compileResult == GL_FALSE) {
- // query information about the compilation (nothing if compilation went fine!)
- glGetShaderInfoLog(vs, 1024, nullptr, buff);
- // print to Visual Studio debug console output
- OutputDebugStringA(buff);
- }
- // repeat process for Fragment Shader (or Pixel Shader)
- GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
- shaderFile.open("Fragment.glsl");
- shaderText.assign((std::istreambuf_iterator<char>(shaderFile)), std::istreambuf_iterator<char>());
- shaderFile.close();
- shaderTextPtr = shaderText.c_str();
- glShaderSource(fs, 1, &shaderTextPtr, nullptr);
- glCompileShader(fs);
- // query information about the compilation (nothing if compilation went fine!)
- compileResult = GL_FALSE;
- glGetShaderiv(fs, GL_COMPILE_STATUS, &compileResult);
- if (compileResult == GL_FALSE) {
- // query information about the compilation (nothing if compilation went fine!)
- memset(buff, 0, 1024);
- glGetShaderInfoLog(fs, 1024, nullptr, buff);
- // print to Visual Studio debug console output
- OutputDebugStringA(buff);
- }
- //link shader program (connect vs and ps)
- gShaderProgram = glCreateProgram();
- glAttachShader(gShaderProgram, fs);
- glAttachShader(gShaderProgram, vs);
- glLinkProgram(gShaderProgram);
- // check once more, if the Vertex Shader and the Fragment Shader can be used
- // together
- compileResult = GL_FALSE;
- glGetProgramiv(gShaderProgram, GL_LINK_STATUS, &compileResult);
- if (compileResult == GL_FALSE) {
- // query information about the compilation (nothing if compilation went fine!)
- memset(buff, 0, 1024);
- glGetProgramInfoLog(gShaderProgram, 1024, nullptr, buff);
- // print to Visual Studio debug console output
- OutputDebugStringA(buff);
- }
- // in any case (compile sucess or not), we only want to keep the
- // Program around, not the shaders.
- glDetachShader(gShaderProgram, vs);
- glDetachShader(gShaderProgram, fs);
- glDeleteShader(vs);
- glDeleteShader(fs);
- }
- void CreateTriangleData()
- {
- // this is how we will structure the input data for the vertex shader
- // every six floats, is one vertex.
- struct TriangleVertex
- {
- float x, y, z;
- float r, g, b;
- float myAttr;
- };
- // create the actual data in plane Z = 0
- // This is called an Array of Structs (AoS) because we will
- // end up with an array of many of these structs.
- TriangleVertex triangleVertices[6] =
- {
- // pos and color for each vertex
- { -0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f },
- { -0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f },
- { 0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 0.0f },
- { -0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f },
- { 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f },
- { 0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 0.0f }
- };
- // Vertex Array Object (VAO), description of the inputs to the GPU
- glGenVertexArrays(1, &gVertexAttribute);
- // bind is like "enabling" the object to use it
- glBindVertexArray(gVertexAttribute);
- // this activates the first and second attributes of this VAO
- // think of "attributes" as inputs to the Vertex Shader
- glEnableVertexAttribArray(0);
- glEnableVertexAttribArray(1);
- glEnableVertexAttribArray(2);
- // create a vertex buffer object (VBO) id (out Array of Structs on the GPU side)
- glGenBuffers(1, &gVertexBuffer);
- // Bind the buffer ID as an ARRAY_BUFFER
- glBindBuffer(GL_ARRAY_BUFFER, gVertexBuffer);
- // This "could" imply copying to the GPU, depending on what the driver wants to do, and
- // the last argument (read the docs!)
- glBufferData(GL_ARRAY_BUFFER, sizeof(triangleVertices), triangleVertices, GL_STATIC_DRAW);
- // query which "slot" corresponds to the input vertex_position in the Vertex Shader
- GLint vertexPos = glGetAttribLocation(gShaderProgram, "vertex_position");
- // if this returns -1, it means there is a problem, and the program will likely crash.
- // examples: the name is different or missing in the shader
- if (vertexPos == -1) {
- OutputDebugStringA("Error, cannot find 'vertex_position' attribute in Vertex shader\n");
- return;
- }
- // tell OpenGL about layout in memory (input assembler information)
- glVertexAttribPointer(
- vertexPos, // location in shader
- 3, // how many elements of type (see next argument)
- GL_FLOAT, // type of each element
- GL_FALSE, // integers will be normalized to [-1,1] or [0,1] when read...
- sizeof(TriangleVertex), // distance between two vertices in memory (stride)
- BUFFER_OFFSET(0) // offset of FIRST vertex in the list.
- );
- // repeat the process for the second attribute.
- // query which "slot" corresponds to the input vertex_color in the Vertex Shader
- GLuint vertexColor = glGetAttribLocation(gShaderProgram, "vertex_color");
- glVertexAttribPointer(
- vertexColor,
- 3,
- GL_FLOAT,
- GL_FALSE, sizeof(TriangleVertex), // distance between two vertexColor
- BUFFER_OFFSET(sizeof(float)*3) // note, the first color starts after the first vertex.
- );
- GLint myAttrLoc = glGetAttribLocation(gShaderProgram, "myAttr");
- glVertexAttribPointer(myAttrLoc, 1, GL_FLOAT, GL_FALSE, sizeof(TriangleVertex), BUFFER_OFFSET(sizeof(float)*6));
- }
- void SetViewport()
- {
- // usually (not necessarily) this matches with the window size
- glViewport(0, 0, WIDTH, HEIGHT);
- }
- void Render()
- {
- glClearColor(0, 0, 0, 1);
- glClear(GL_COLOR_BUFFER_BIT);
- glUseProgram(gShaderProgram);
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, bth_tex);
- glBindVertexArray(gVertexAttribute);
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
- // set the color TO BE used (this does not clear the screen right away)
- glClearColor(gClearColour[0], gClearColour[1],gClearColour[2],1.0);
- // use the color to clear the color buffer (clear the color buffer only)
- glClear(GL_COLOR_BUFFER_BIT);
- // tell opengl we want to use the gShaderProgram
- glUseProgram(gShaderProgram);
- glUniform3fv(gUniformColourLoc, 1, &gUniformColour[0]);
- GLuint MatrixIDWorld = glGetUniformLocation(gShaderProgram, "WorldMatrix");
- glUniformMatrix4fv(MatrixIDWorld, 1, GL_FALSE, glm::value_ptr(WorldMatrix));
- GLuint MatrixIDView = glGetUniformLocation(gShaderProgram, "ViewMatrix");
- glUniformMatrix4fv(MatrixIDView, 1, GL_FALSE, glm::value_ptr(ViewMatrix));
- GLuint MatrixIDProjection = glGetUniformLocation(gShaderProgram, "ProjectionMatrix");
- glUniformMatrix4fv(MatrixIDProjection, 1, GL_FALSE, glm::value_ptr(ProjectionMatrix));
- // tell opengl we are going to use the VAO we described earlier
- glBindVertexArray(gVertexAttribute);
- // ask OpenGL to draw 3 vertices starting from index 0 in the vertex array
- // currently bound (VAO), with current in-use shader. Use TOPOLOGY GL_TRIANGLES,
- // so for one triangle we need 3 vertices!
- glDrawArrays(GL_TRIANGLES, 0, 6);
- }
- int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow )
- {
- MSG msg = { 0 };
- HWND wndHandle = InitWindow(hInstance); // 1. Skapa fönster
- if (wndHandle)
- {
- HDC hDC = GetDC(wndHandle);
- HGLRC hRC = CreateOpenGLContext(wndHandle); //2. Skapa och koppla OpenGL context
- glewInit(); //3. Initiera The OpenGL Extension Wrangler Library (GLEW)
- IMGUI_CHECKVERSION();
- ImGui::CreateContext();
- ImGuiIO& io = ImGui::GetIO(); (void)io;
- ImGui_ImplWin32_Init(wndHandle);
- ImGui_ImplOpenGL3_Init();
- ImGui::StyleColorsDark();
- // which OpenGL did we get?
- GLint glMajor, glMinor;
- glGetIntegerv(GL_MAJOR_VERSION, &glMajor);
- glGetIntegerv(GL_MAJOR_VERSION, &glMinor);
- char buff[256] = {};
- sprintf_s(buff, 256, "OpenGL context version %d.%d created\n", glMajor, glMinor);
- OutputDebugStringA(buff);
- SetViewport(); //4. Sätt viewport
- CreateShaders(); //5. Skapa vertex- och fragment-shaders
- CreateTriangleData(); //6. Definiera triangelvertiser, 7. Skapa vertex buffer object (VBO), 8.Skapa vertex array object (VAO)
- int width, height, nrChannels;
- ShowWindow(wndHandle, nCmdShow);
- gUniformColourLoc = glGetUniformLocation(gShaderProgram, "colourFromImGui");
- while (WM_QUIT != msg.message)
- {
- if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- else
- {
- // move along X
- gIncrement += 1.0f * ImGui::GetIO().DeltaTime;
- if( gIncrement > 360){
- gIncrement == 0;
- }
- createMatrix(gIncrement); // 4.5 Skapar matriser (own)
- // prepare IMGUI output
- ImGui_ImplOpenGL3_NewFrame();
- ImGui_ImplWin32_NewFrame();
- ImGui::NewFrame();
- ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
- ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
- ImGui::SliderFloat("float", &gFloat, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
- ImGui::ColorEdit3("clear color", gClearColour); // Edit 3 floats representing a color
- ImGui::ColorEdit3("triangle color", gUniformColour);
- ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
- ImGui::End();
- Render(); //9. Rendera
- // actually render IMGUI interface
- ImGui::Render();
- ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
- SwapBuffers(hDC); //10. Växla front- och back-buffer
- }
- }
- ImGui_ImplOpenGL3_Shutdown();
- ImGui_ImplWin32_Shutdown();
- ImGui::DestroyContext();
- // release OpenGL context
- wglMakeCurrent(NULL, NULL);
- // release device context handle
- ReleaseDC(wndHandle, hDC);
- // delete context
- wglDeleteContext(hRC);
- // kill window
- DestroyWindow(wndHandle);
- }
- return (int) msg.wParam;
- }
- // Win32 specific code. Create a window with certain characteristics
- HWND InitWindow(HINSTANCE hInstance)
- {
- WNDCLASSEX wcex = { 0 };
- wcex.cbSize = sizeof(WNDCLASSEX);
- wcex.style = CS_HREDRAW | CS_VREDRAW;
- wcex.lpfnWndProc = WndProc;
- wcex.hInstance = hInstance;
- wcex.lpszClassName = L"BTH_GL_DEMO";
- if( !RegisterClassEx(&wcex) )
- return false;
- // window size
- RECT rc = { 0, 0, WIDTH, HEIGHT };
- AdjustWindowRect( &rc, WS_OVERLAPPEDWINDOW, FALSE );
- // win32 call to create a window
- HWND handle = CreateWindow(
- L"BTH_GL_DEMO",
- L"BTH OpenGL Demo",
- WS_OVERLAPPEDWINDOW,
- CW_USEDEFAULT,
- CW_USEDEFAULT,
- rc.right - rc.left,
- rc.bottom - rc.top,
- nullptr,
- nullptr,
- hInstance,
- nullptr);
- return handle;
- }
- extern LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
- LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
- {
- if (ImGui_ImplWin32_WndProcHandler(hWnd, message, wParam, lParam))
- return true;
- switch (message)
- {
- case WM_DESTROY:
- PostQuitMessage(0);
- break;
- }
- return DefWindowProc(hWnd, message, wParam, lParam);
- }
- HGLRC CreateOpenGLContext(HWND wndHandle)
- {
- //get handle to a device context (DC) for the client area
- //of a specified window or for the entire screen
- HDC hDC = GetDC(wndHandle);
- //details: http://msdn.microsoft.com/en-us/library/windows/desktop/dd318286(v=vs.85).aspx
- static PIXELFORMATDESCRIPTOR pixelFormatDesc =
- {
- sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd
- 1, // version number
- PFD_DRAW_TO_WINDOW | // support window
- PFD_SUPPORT_OPENGL | // support OpenGL
- PFD_DOUBLEBUFFER | // double buffered
- PFD_DEPTH_DONTCARE, // disable depth buffer <-- added by Stefan
- PFD_TYPE_RGBA, // RGBA type
- 32, // 32-bit color depth (4*8)
- 0, 0, 0, 0, 0, 0, // color bits ignored
- 0, // no alpha buffer
- 0, // shift bit ignored
- 0, // no accumulation buffer
- 0, 0, 0, 0, // accum bits ignored
- 0, // 24 // 0-bits for depth buffer <-- modified by Stefan
- 0, // 8 // no stencil buffer
- 0, // no auxiliary buffer
- PFD_MAIN_PLANE, // main layer
- 0, // reserved
- 0, 0, 0 // layer masks ignored
- };
- //attempt to match an appropriate pixel format supported by a
- //device context to a given pixel format specification.
- int pixelFormat = ChoosePixelFormat(hDC, &pixelFormatDesc);
- //set the pixel format of the specified device context
- //to the format specified by the iPixelFormat index.
- SetPixelFormat(hDC, pixelFormat, &pixelFormatDesc);
- //create a new OpenGL rendering context, which is suitable for drawing
- //on the device referenced by hdc. The rendering context has the same
- //pixel format as the device context.
- HGLRC hRC = wglCreateContext(hDC);
- //makes a specified OpenGL rendering context the calling thread's current
- //rendering context. All subsequent OpenGL calls made by the thread are
- //drawn on the device identified by hdc.
- wglMakeCurrent(hDC, hRC);
- return hRC;
- }
- #version 440
- layout(location = 0) in vec3 vertex_position;
- layout(location = 1) in vec3 vertex_tex;
- layout(location = 2) in float myAttr;
- layout(location = 0) out vec2 texOut;
- layout(location=3) out float myAttrOut;
- uniform mat4 WorldMatrix;
- uniform mat4 ViewMatrix;
- uniform mat4 ProjectionMatrix;
- void main() {
- texOut = vertex_tex;
- myAttrOut = myAttr;
- gl_Position = WorldMatrix * vec4(vec3(vertex_position.x,vertex_position.yz), 1.0);
- }
- #version 440
- // these values are interpolated at the rasteriser
- layout(location = 0) in vec2 texIn;
- uniform sampler2D texSampler;
- layout(location=3) in float myAttrOut;
- // this is the final pixel colour
- out vec4 fragment_color;
- // this is a uniform value, the very same value for ALL pixel shader executions
- layout(location = 5) uniform vec3 colourFromImGui;
- void main () {
- vec4 mySample = texture(texSampler, vec2(texIn.S,1-texIn.t //vec4 (color, 1.0);
- fragment_color = mySample.rgb;
- //fragment_color = myAttrOut * vec4 (color * colourFromImGui, 1.0);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement