#include <iostream> #include <cmath> #include <functional> #include <SFML/Window.hpp> #include <SFML/Graphics.hpp> #include <glad/glad.h> #include <SFML/OpenGL.hpp> #include <glm/glm.hpp> #include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/type_ptr.hpp> // Vertex Shader const char *vertexShaderSource = R"glsl( #version 450 core layout (location = 0) in vec3 aPos; layout (location = 1) in vec2 aTexCoord; out vec2 TexCoord; uniform mat4 vModel; uniform mat4 vView; uniform mat4 vProjection; void main() { gl_Position = vProjection * vView * vModel * vec4(aPos, 1.0); TexCoord = aTexCoord; } )glsl"; // Fragment Shader const char *fragmentShaderSoucre = R"glsl( #version 450 core out vec4 FragColor; in vec2 TexCoord; in vec3 VertColor; uniform sampler2D tex1; uniform sampler2D tex2; uniform vec4 fColor; uniform float fMix; void main() { vec4 resultColor = mix(texture(tex1, TexCoord), texture(tex2, TexCoord), fMix) * fColor; FragColor = resultColor; } )glsl"; uint32_t LoadShader(GLenum type, const char* src) { uint32_t shader; shader = glCreateShader(type); glShaderSource(shader, 1, &src, nullptr); glCompileShader(shader); int success; char log[512]; glGetShaderiv(shader, GL_COMPILE_STATUS, &success); if(!success) { glGetShaderInfoLog(shader, 512, nullptr, log); printf("Error Shader %s compile error\n%s\n", type == GL_VERTEX_SHADER ? "Vertex" : "Fragment", log); return 0; } return shader; } uint32_t LinkShaderProgram(uint32_t vertex, uint32_t fragment) { uint32_t program = glCreateProgram(); glAttachShader(program, vertex); glAttachShader(program, fragment); glLinkProgram(program); // int success; char log[512]; glGetProgramiv(program, GL_LINK_STATUS, &success); if(!success) { glGetProgramInfoLog(program, 512, nullptr, log); printf("Error Shader Linking error\n%s\n", log); return 0; } return program; } float vertices[] = { -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, -0.5f, 0.5f, 0.5f, 1.0f, 0.0f, -0.5f, 0.5f, -0.5f, 1.0f, 1.0f, -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, -0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, -0.5f, 0.5f, -0.5f, 0.0f, 1.0f }; uint32_t indices[] = { 0, 1, 3, // 第一個三角形 1, 2, 3 // 第二個三角形 }; const uint32_t screenWidth = 1280, screenHeight = 720; int main() { sf::RenderWindow window(sf::VideoMode(screenWidth, screenHeight), "OpenGL", sf::Style::Default, sf::ContextSettings(24, 8, 4, 4, 4)); window.setVerticalSyncEnabled(true); // Load OpenGL functions using glad if (!gladLoadGL()) { printf("Something went wrong!\n"); exit(-1); } printf("OpenGL %s, GLSL %s\n", glGetString(GL_VERSION), glGetString(GL_SHADING_LANGUAGE_VERSION)); window.setActive(true); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_DEPTH_TEST); // Load shader uint32_t vertexShader = LoadShader(GL_VERTEX_SHADER, vertexShaderSource); uint32_t fragmentShader = LoadShader(GL_FRAGMENT_SHADER, fragmentShaderSoucre); uint32_t program; if(vertexShader && fragmentShader) { program = LinkShaderProgram(vertexShader, fragmentShader); glUseProgram(program); glDeleteShader(vertexShader); glDeleteShader(fragmentShader); } else { return 1; } // Load vertices // VAO uint32_t vao; glGenVertexArrays(1, &vao); glBindVertexArray(vao); // VBO uint32_t vbo; glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); // EBO uint32_t ebo; glGenBuffers(1, &ebo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); // Specify Vertex Attribute uint32_t aPos = glGetAttribLocation(program, "aPos"); glVertexAttribPointer(aPos, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void *)0); glEnableVertexAttribArray(aPos); uint32_t aTexCoord = glGetAttribLocation(program, "aTexCoord"); glVertexAttribPointer(aTexCoord, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3*sizeof(float))); glEnableVertexAttribArray(aTexCoord); // Texture auto LoadTexture = [&](std::string path) { sf::Image img; img.loadFromFile(path); img.flipVertically(); // generate a texture uint32_t texture; glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); // texture parameter glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img.getSize().x, img.getSize().y, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)img.getPixelsPtr()); glGenerateMipmap(GL_TEXTURE_2D); return texture; }; uint32_t wall_tex = LoadTexture("3.jpg"); uint32_t lambda_tex = LoadTexture("1.png"); glUseProgram(program); glUniform1i(glGetUniformLocation(program, "tex1"), 0); glUniform1i(glGetUniformLocation(program, "tex2"), 1); sf::Clock stClk; sf::Clock deltaClock; bool running = true; while (running) { sf::Event event; while (window.pollEvent(event)) { if (event.type == sf::Event::Closed) running = false; else if (event.type == sf::Event::Resized) glViewport(0, 0, event.size.width, event.size.height); } static bool wire_mode = false; // tint static float tintColor[4] = {1.f, 1.f, 1.f, 1.f}; // mix static float mix = 0.2f; static float bgColor[4]; glm::mat4 model(1.f), view(1.f), projection(1.f); static float rotate_x = -55.0f, rotate_y = 0.f, rotate_z = 0.f; float step = stClk.getElapsedTime().asMilliseconds()/10; rotate_x = step; rotate_y = step; rotate_x = fmod(rotate_x, 360); rotate_y = fmod(rotate_y, 360); model = glm::rotate(model, glm::radians(rotate_x), glm::vec3(1.0f, 0.0f, 0.0f)); model = glm::rotate(model, glm::radians(rotate_y), glm::vec3(0.0f, 1.0f, 0.0f)); model = glm::rotate(model, glm::radians(rotate_z), glm::vec3(0.0f, 0.0f, 1.0f)); static float trans[3] = {0.0f, 0.0f, -3.0f}; view = glm::translate(view, glm::vec3(trans[0], trans[1], trans[2])); static float fov = 45.f; projection = glm::perspective(glm::radians(fov), (float)screenWidth / screenHeight, 0.1f, 100.f); glClearColor(bgColor[0], bgColor[1], bgColor[2], bgColor[3]); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 將 wall_tex 綁到 GL_TEXTURE0 glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, wall_tex); // 將 lambda_tex 綁到 GL_TEXTURE1 glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, lambda_tex); // Upload uniforms glUseProgram(program); static int colorLoc = glGetUniformLocation(program, "fColor"); glUniform4f(colorLoc, tintColor[0], tintColor[1], tintColor[2], tintColor[3]); static int mixLoc = glGetUniformLocation(program, "fMix"); glUniform1f(mixLoc, mix); auto UploadMat4 = [&](const std::string &name, glm::mat4 &mat4) { int uniformLoc = glGetUniformLocation(program, name.c_str()); glUniformMatrix4fv(uniformLoc, 1, GL_FALSE, glm::value_ptr(mat4)); }; UploadMat4("vModel", model); UploadMat4("vView", view); UploadMat4("vProjection", projection); // glBindVertexArray(vao); glDrawArrays(GL_TRIANGLES, 0, 36); glBindVertexArray(0); window.display(); } // release resources... glDeleteVertexArrays(1, &vao); glDeleteBuffers(1, &vbo); glDeleteBuffers(1, &ebo); glDeleteProgram(program); return 0; }
Select a repo