opengl实现晶圆排列

  • opengl实现以下功能
  • 1、用opengl创建一个800*800的窗口
  • 2、用蓝色创建半径400的圆
  • 3、在圆内布满2*2的正方形,用绿色线画
  • 4、鼠标点击正方形,改变其颜色为红色,抬起鼠标回复绿色
  • 5、点击正方形,输出其中心坐标
  • 在这里插入图片描述
#include<glad/glad.h>
#include<GLFW/glfw3.h>
#include<iostream>
#include<cmath>
#include<vector>

// settings
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 800;
const float CIRCLE_RADIUS = 0.5f; // 归一化坐标下的半径
const float SQUARE_SIZE = 0.005f; // 归一化坐标下的正方形大小

// 缩放因子
float scaleFactor = 1.0f;
const float SCALE_STEP = 0.1f;

// 鼠标位置
float mouseX = 0.0f;
float mouseY = 0.0f;

// 顶点着色器代码
const char* vertexShaderSource = R"(
#version 330 core
layout (location = 0) in vec2 aPos;
uniform float scale;
uniform vec2 mousePos;

void main()
{
    // 先将顶点平移到以鼠标位置为原点
    vec2 translated = aPos - mousePos;
    // 进行缩放操作
    vec2 scaled = translated * scale;
    // 再平移回原来的位置
    vec2 finalPos = scaled + mousePos;
    gl_Position = vec4(finalPos, 0.0, 1.0);
}
)";

// 片段着色器代码
const char* fragmentShaderSource = R"(
#version 330 core
out vec4 FragColor;
uniform vec4 color;

void main()
{
    FragColor = color;
}
)";

// 正方形结构体
struct Square {
    float x, y;
    bool isClicked = false;
};

std::vector<Square> squares;

void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void mouse_button_callback(GLFWwindow* window, int button, int action, int mods);
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
void cursor_position_callback(GLFWwindow* window, double xpos, double ypos);
std::vector<float> generateCircleVertices(float x, float y, float radius, int numSegments);
void generateSquaresInCircle();
void drawCircle(unsigned int shaderProgram, unsigned int VAO, unsigned int VBO);
void drawSquares(unsigned int shaderProgram, unsigned int VAO, unsigned int VBO);

int main()
{
    int glfwSate = glfwInit();
    if (glfwSate == GLFW_FALSE)
    {
        std::cout << "GLFW initialize failed!" << std::endl;
        exit(EXIT_FAILURE);
    }

    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

    GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "OpenGL Circle and Squares with Zoom", NULL, NULL);
    if (window == NULL)
    {
        std::cout << "Failed to create GLFW window" << std::endl;
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);

    // glad: load all OpenGL function pointers
    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
    {
        std::cout << "Failed to initialize GLAD" << std::endl;
        return -1;
    }

    glViewport(0, 0, SCR_WIDTH, SCR_HEIGHT);
    glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
    glfwSetMouseButtonCallback(window, mouse_button_callback);
    glfwSetScrollCallback(window, scroll_callback);
    glfwSetCursorPosCallback(window, cursor_position_callback);

    // 创建顶点着色器
    unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vertexShaderSource, nullptr);
    glCompileShader(vertexShader);

    // 检查顶点着色器编译错误
    int success;
    char infoLog[512];
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
    if (!success) {
        glGetShaderInfoLog(vertexShader, 512, nullptr, infoLog);
        std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
    }

    // 创建片段着色器
    unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fragmentShaderSource, nullptr);
    glCompileShader(fragmentShader);

    // 检查片段着色器编译错误
    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
    if (!success) {
        glGetShaderInfoLog(fragmentShader, 512, nullptr, infoLog);
        std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
    }

    // 链接着色器程序
    unsigned int shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);

    // 检查着色器程序链接错误
    glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
    if (!success) {
        glGetProgramInfoLog(shaderProgram, 512, nullptr, infoLog);
        std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
    }

    // 删除着色器
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);

    // 生成圆的顶点数据
    std::vector<float> circleVertices = generateCircleVertices(0.0f, 0.0f, CIRCLE_RADIUS, 100);

    // 创建 VAO 和 VBO 用于圆
    unsigned int circleVAO, circleVBO;
    glGenVertexArrays(1, &circleVAO);
    glGenBuffers(1, &circleVBO);

    // 绑定 VAO 和 VBO
    glBindVertexArray(circleVAO);
    glBindBuffer(GL_ARRAY_BUFFER, circleVBO);
    glBufferData(GL_ARRAY_BUFFER, circleVertices.size() * sizeof(float), circleVertices.data(), GL_STATIC_DRAW);

    // 设置顶点属性
    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);

    // 解绑 VAO 和 VBO
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);

    // 生成圆内的正方形
    generateSquaresInCircle();

    // 创建 VAO 和 VBO 用于正方形
    unsigned int squareVAO, squareVBO;
    glGenVertexArrays(1, &squareVAO);
    glGenBuffers(1, &squareVBO);

    while (!glfwWindowShouldClose(window))
    {
        // 清除颜色缓冲区
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        // 绘制圆
        drawCircle(shaderProgram, circleVAO, circleVBO);
        // 绘制正方形
        drawSquares(shaderProgram, squareVAO, squareVBO);

        glfwSwapBuffers(window);
        glfwPollEvents();
    }

    // 删除 VAO 和 VBO
    glDeleteVertexArrays(1, &circleVAO);
    glDeleteBuffers(1, &circleVBO);
    glDeleteVertexArrays(1, &squareVAO);
    glDeleteBuffers(1, &squareVBO);

    glfwTerminate();
    return 0;
}

void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
    glViewport(0, 0, width, height);
}

void mouse_button_callback(GLFWwindow* window, int button, int action, int mods)
{
    if (button == GLFW_MOUSE_BUTTON_LEFT) {
        if (action == GLFW_PRESS) {
            double xpos, ypos;
            glfwGetCursorPos(window, &xpos, &ypos);

            // 将鼠标坐标转换为归一化设备坐标
            float mouseX = (2.0f * xpos) / SCR_WIDTH - 1.0f;
            float mouseY = 1.0f - (2.0f * ypos) / SCR_HEIGHT;

            for (auto& square : squares) {
                if (mouseX >= square.x * scaleFactor && mouseX <= (square.x + SQUARE_SIZE) * scaleFactor &&
                    mouseY >= square.y * scaleFactor && mouseY <= (square.y + SQUARE_SIZE) * scaleFactor) {
                    square.isClicked = true;
                    float centerX = (square.x + SQUARE_SIZE / 2) * scaleFactor;
                    float centerY = (square.y + SQUARE_SIZE / 2) * scaleFactor;
                    std::cout << "Clicked square center coordinates: (" << centerX << ", " << centerY << ")" << std::endl;
                }
            }
        }
        else if (action == GLFW_RELEASE) {
            for (auto& square : squares) {
                square.isClicked = false;
            }
        }
    }
}

void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
{
    double xpos, ypos;
    glfwGetCursorPos(window, &xpos, &ypos);
    // 将鼠标坐标转换为归一化设备坐标
    mouseX = (2.0f * xpos) / SCR_WIDTH - 1.0f;
    mouseY = 1.0f - (2.0f * ypos) / SCR_HEIGHT;

    if (yoffset > 0) {
        // 向上滚动,放大
        scaleFactor += SCALE_STEP;
    }
    else {
        // 向下滚动,缩小
        if (scaleFactor > SCALE_STEP) {
            scaleFactor -= SCALE_STEP;
        }
    }
}

void cursor_position_callback(GLFWwindow* window, double xpos, double ypos)
{
    // 这里可以根据需要添加鼠标移动时的逻辑
    // 目前我们只在滚动时更新鼠标位置
}

std::vector<float> generateCircleVertices(float x, float y, float radius, int numSegments) {
    std::vector<float> vertices;
    for (int i = 0; i < numSegments; i++) {
        float angle = 2.0f * 3.1415926f * float(i) / float(numSegments);
        float dx = radius * cosf(angle);
        float dy = radius * sinf(angle);
        vertices.push_back(x + dx);
        vertices.push_back(y + dy);
    }
    return vertices;
}

void generateSquaresInCircle() {
    for (float y = -CIRCLE_RADIUS; y < CIRCLE_RADIUS; y += SQUARE_SIZE) {
        for (float x = -CIRCLE_RADIUS; x < CIRCLE_RADIUS; x += SQUARE_SIZE) {
            if (std::sqrt(x * x + y * y) <= CIRCLE_RADIUS) {
                squares.push_back({ x, y });
            }
        }
    }
}

void drawCircle(unsigned int shaderProgram, unsigned int VAO, unsigned int VBO) {
    glUseProgram(shaderProgram);
    glBindVertexArray(VAO);

    // 设置缩放因子
    int scaleLocation = glGetUniformLocation(shaderProgram, "scale");
    glUniform1f(scaleLocation, scaleFactor);

    // 设置鼠标位置
    int mousePosLocation = glGetUniformLocation(shaderProgram, "mousePos");
    glUniform2f(mousePosLocation, mouseX, mouseY);

    // 设置圆的颜色为蓝色
    int colorLocation = glGetUniformLocation(shaderProgram, "color");
    glUniform4f(colorLocation, 0.0f, 0.0f, 1.0f, 1.0f);

    glDrawArrays(GL_TRIANGLE_FAN, 0, 100);
    glBindVertexArray(0);
}

void drawSquares(unsigned int shaderProgram, unsigned int VAO, unsigned int VBO) {
    glUseProgram(shaderProgram);
    glBindVertexArray(VAO);

    std::vector<float> squareVertices;
    for (const auto& square : squares) {
        float x = square.x;
        float y = square.y;
        squareVertices.insert(squareVertices.end(), {
            x, y,
            x + SQUARE_SIZE, y,
            x + SQUARE_SIZE, y + SQUARE_SIZE,
            x, y + SQUARE_SIZE
            });
    }

    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, squareVertices.size() * sizeof(float), squareVertices.data(), GL_DYNAMIC_DRAW);

    // 设置顶点属性
    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);

    // 设置缩放因子
    int scaleLocation = glGetUniformLocation(shaderProgram, "scale");
    glUniform1f(scaleLocation, scaleFactor);

    // 设置鼠标位置
    int mousePosLocation = glGetUniformLocation(shaderProgram, "mousePos");
    glUniform2f(mousePosLocation, mouseX, mouseY);

    int colorLocation = glGetUniformLocation(shaderProgram, "color");
    for (size_t i = 0; i < squares.size(); ++i) {
        if (squares[i].isClicked) {
            glUniform4f(colorLocation, 1.0f, 0.0f, 0.0f, 1.0f); // 红色
            // 填充正方形内部
            glDrawArrays(GL_TRIANGLE_FAN, i * 4, 4);
        }
        else {
            glUniform4f(colorLocation, 0.0f, 1.0f, 0.0f, 1.0f); // 绿色
            // 只绘制正方形边框
            glDrawArrays(GL_LINE_LOOP, i * 4, 4);
        }
    }

    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值