第2章 现代图形系统架构与技术实现

第2章 现代图形系统架构与技术实现

2.1 图形显示技术与设备原理

现代图形显示设备经历了从CRT到LCD、OLED的革命性发展。理解这些设备的原理对于图形编程至关重要。

显示技术理论基础

CRT(阴极射线管):通过电子束轰击荧光粉发光,采用逐行或隔行扫描LCD(液晶显示):通过液晶分子控制光线通过,需要背光OLED(有机发光二极管):每个像素自发光,对比度高,响应快

刷新率与同步
垂直同步(VSync)技术防止画面撕裂,通过将帧率与显示器刷新率同步来实现。


// DisplaySystem.h - 显示系统模拟
#ifndef DISPLAY_SYSTEM_H
#define DISPLAY_SYSTEM_H

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <vector>
#include <chrono>

class DisplaySystem {
public:
    enum DisplayType {
        CRT_SIMULATION,
        LCD_SIMULATION,
        OLED_SIMULATION
    };
    
    DisplaySystem();
    ~DisplaySystem();
    
    bool initialize(int width, int height, DisplayType type);
    void render();
    void update();
    void cleanup();
    
    void setVSync(bool enabled);
    void setRefreshRate(int hz);
    
private:
    GLFWwindow* m_window;
    DisplayType m_displayType;
    bool m_vsyncEnabled;
    int m_refreshRate;
    int m_width, m_height;
    
    unsigned int m_shaderProgram;
    unsigned int m_VAO, m_VBO, m_EBO;
    unsigned int m_texture;
    
    std::chrono::high_resolution_clock::time_point m_lastFrameTime;
    double m_frameTimeAccumulator;
    int m_frameCount;
    
    void compileShaders();
    void setupGeometry();
    void simulateCRTEffect();
    void simulateLCDEffect();
    void simulateOLEDEffect();
    void updateFrameStats();
};

#endif

// DisplaySystem.cpp
#include "DisplaySystem.h"
#include <iostream>
#include <random>

const char* displayVertexShader = R"(
#version 330 core
layout (location = 0) in vec2 aPos;
layout (location = 1) in vec2 aTexCoord;

out vec2 TexCoord;

void main() {
    gl_Position = vec4(aPos, 0.0, 1.0);
    TexCoord = aTexCoord;
}
)";

const char* displayFragmentShader = R"(
#version 330 core
out vec4 FragColor;
in vec2 TexCoord;

uniform sampler2D screenTexture;
uniform int displayType;
uniform float time;

// CRT扫描线效果
vec3 crtEffect(vec3 color, vec2 uv) {
    float scanline = sin(uv.y * 800.0 * 3.14159 * 2.0 + time * 5.0) * 0.05 + 0.95;
    color *= scanline;
    
    // 模拟CRT边缘失真
    vec2 distortedUV = (uv - 0.5) * 0.98 + 0.5;
    color *= texture(screenTexture, distortedUV).rgb;
    
    return color;
}

// LCD像素网格效果
vec3 lcdEffect(vec3 color, vec2 uv) {
    vec2 pixelUV = uv * vec2(1920.0, 1080.0);
    vec2 grid = fract(pixelUV);
    
    // RGB子像素排列
    if (grid.x < 0.33) {
        color.g *= 0.8;
        color.b *= 0.8;
    } else if (grid.x < 0.66) {
        color.r *= 0.8;
        color.b *= 0.8;
    } else {
        color.r *= 0.8;
        color.g *= 0.8;
    }
    
    return color;
}

// OLED纯色效果(无额外处理,但可以模拟像素自发光)
vec3 oledEffect(vec3 color, vec2 uv) {
    // OLED对比度增强
    color = pow(color, vec3(1.1));
    return color;
}

void main() {
    vec3 color = texture(screenTexture, TexCoord).rgb;
    
    if (displayType == 0) {
        color = crtEffect(color, TexCoord);
    } else if (displayType == 1) {
        color = lcdEffect(color, TexCoord);
    } else if (displayType == 2) {
        color = oledEffect(color, TexCoord);
    }
    
    FragColor = vec4(color, 1.0);
}
)";

DisplaySystem::DisplaySystem() 
    : m_window(nullptr), m_displayType(CRT_SIMULATION)
    , m_vsyncEnabled(true), m_refreshRate(60)
    , m_width(800), m_height(600)
    , m_shaderProgram(0), m_VAO(0), m_VBO(0), m_EBO(0), m_texture(0)
    , m_frameTimeAccumulator(0.0), m_frameCount(0) {
    
    m_lastFrameTime = std::chrono::high_resolution_clock::now();
}

DisplaySystem::~DisplaySystem() {
    cleanup();
}

bool DisplaySystem::initialize(int width, int height, DisplayType type) {
    m_width = width;
    m_height = height;
    m_displayType = type;
    
    if (!glfwInit()) {
        std::cerr << "GLFW初始化失败!" << std::endl;
        return false;
    }
    
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    
    m_window = glfwCreateWindow(width, height, "显示系统模拟", nullptr, nullptr);
    if (!m_window) {
        std::cerr << "创建窗口失败!" << std::endl;
        glfwTerminate();
        return false;
    }
    
    glfwMakeContextCurrent(m_window);
    
    if (glewInit() != GLEW_OK) {
        std::cerr << "GLEW初始化失败!" << std::endl;
        return false;
    }
    
    setVSync(m_vsyncEnabled);
    
    compileShaders();
    setupGeometry();
    
    // 创建测试纹理
    glGenTextures(1, &m_texture);
    glBindTexture(GL_TEXTURE_2D, m_texture);
    
    std::vector<unsigned char> textureData(width * height * 3);
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<> dis(0, 255);
    
    for (int i = 0; i < width * height * 3; i++) {
        textureData[i] = dis(gen);
    }
    
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData.data());
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    
    return true;
}

void DisplaySystem::compileShaders() {
    unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &displayVertexShader, nullptr);
    glCompileShader(vertexShader);
    
    unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &displayFragmentShader, nullptr);
    glCompileShader(fragmentShader);
    
    m_shaderProgram = glCreateProgram();
    glAttachShader(m_shaderProgram, vertexShader);
    glAttachShader(m_shaderProgram, fragmentShader);
    glLinkProgram(m_shaderProgram);
    
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);
}

void DisplaySystem::setupGeometry() {
    // 全屏四边形
    float vertices[] = {
        // 位置          // 纹理坐标
        -1.0f,  1.0f,   0.0f, 1.0f,
        -1.0f, -1.0f,   0.0f, 0.0f,
         1.0f, -1.0f,   1.0f, 0.0f,
         1.0f,  1.0f,   1.0f, 1.0f
    };
    
    unsigned int indices[] = {
        0, 1, 2,
        0, 2, 3
    };
    
    glGenVertexArrays(1, &m_VAO);
    glGenBuffers(1, &m_VBO);
    glGenBuffers(1, &m_EBO);
    
    glBindVertexArray(m_VAO);
    
    glBindBuffer(GL_ARRAY_BUFFER, m_VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
    
    // 位置属性
    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);
    // 纹理坐标属性
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float)));
    glEnableVertexAttribArray(1);
    
    glBindVertexArray(0);
}

void DisplaySystem::setVSync(bool enabled) {
    m_vsyncEnabled = enabled;
    glfwSwapInterval(enabled ? 1 : 0);
}

void DisplaySystem::setRefreshRate(int hz) {
    m_refreshRate = hz;
}

void DisplaySystem::update() {
    auto currentTime = std::chrono::high_resolution_clock::now();
    double deltaTime = std::chrono::duration<double>(currentTime - m_lastFrameTime).count();
    m_lastFrameTime = currentTime;
    
    m_frameTimeAccumulator += deltaTime;
    m_frameCount++;
    
    if (m_frameTimeAccumulator >= 1.0) {
        updateFrameStats();
        m_frameTimeAccumulator = 0.0;
        m_frameCount = 0;
    }
}

void DisplaySystem::updateFrameStats() {
    double fps = m_frameCount / 1.0;
    std::cout << "FPS: " << fps << " | VSync: " << (m_vsyncEnabled ? "On" : "Off") << std::endl;
}

void DisplaySystem::render() {
    glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);
    
    glUseProgram(m_shaderProgram);
    
    // 设置uniform
    float time = glfwGetTime();
    glUniform1f(glGetUniformLocation(m_shaderProgram, "time"), time);
    glUniform1i(glGetUniformLocation(m_shaderProgram, "displayType"), static_cast<int>(m_displayType));
    
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, m_texture);
    glUniform1i(glGetUniformLocation(m_shaderProgram, "screenTexture"), 0);
    
    glBindVertexArray(m_VAO);
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
    
    glfwSwapBuffers(m_window);
}

void DisplaySystem::cleanup() {
    if (m_shaderProgram) glDeleteProgram(m_shaderProgram);
    if (m_VAO) glDeleteVertexArrays(1, &m_VAO);
    if (m_VBO) glDeleteBuffers(1, &m_VBO);
    if (m_EBO) glDeleteBuffers(1, &m_EBO);
    if (m_texture) glDeleteTextures(1, &m_texture);
    
    if (m_window) {
        glfwDestroyWindow(m_window);
        glfwTerminate();
    }
}

2.2 光栅扫描与帧缓冲技术

光栅扫描是计算机图形学的核心技术,它将矢量图形转换为像素阵列进行显示。

光栅化原理

扫描线算法多边形填充反走样技术


// Rasterizer.h - 软件光栅化器
#ifndef RASTERIZER_H
#define RASTERIZER_H

#include <vector>
#include <cstdint>
#include <algorithm>
#include <cmath>

struct Color {
    uint8_t r, g, b, a;
    
    Color(uint8_t red = 0, uint8_t green = 0, uint8_t blue = 0, uint8_t alpha = 255) 
        : r(red), g(green), b(blue), a(alpha) {}
};

struct Point {
    int x, y;
    Point(int x = 0, int y = 0) : x(x), y(y) {}
};

struct Triangle {
    Point v0, v1, v2;
    Color color;
    
    Triangle(Point p0, Point p1, Point p2, Color c = Color()) 
        : v0(p0), v1(p1), v2(p2), color(c) {}
};

class SoftwareRasterizer {
public:
    SoftwareRasterizer(int width, int height);
    ~SoftwareRasterizer();
    
    void clear(const Color& color);
    void setPixel(int x, int y, const Color& color);
    void drawLine(const Point& p0, const Point& p1, const Color& color);
    void drawTriangle(const Triangle& triangle);
    void drawCircle(const Point& center, int radius, const Color& color);
    
    void* getFramebuffer() const { return m_framebuffer; }
    int getWidth() const { return m_width; }
    int getHeight() const { return m_height; }
    
private:
    int m_width, m_height;
    uint8_t* m_framebuffer;
    
    void drawLineLow(const Point& p0, const Point& p1, const Color& color);
    void drawLineHigh(const Point& p0, const Point& p1, const Color& color);
    void edgeFunction(const Point& a, const Point& b, const Point& p, float& result);
};

#endif

// Rasterizer.cpp
#include "Rasterizer.h"
#include <cstring>

SoftwareRasterizer::SoftwareRasterizer(int width, int height) 
    : m_width(width), m_height(height) {
    
    // 分配帧缓冲区 (RGBA格式)
    m_framebuffer = new uint8_t[width * height * 4];
    clear(Color(0, 0, 0, 255));
}

SoftwareRasterizer::~SoftwareRasterizer() {
    delete[] m_framebuffer;
}

void SoftwareRasterizer::clear(const Color& color) {
    for (int i = 0; i < m_width * m_height * 4; i += 4) {
        m_framebuffer[i] = color.r;     // R
        m_framebuffer[i + 1] = color.g; // G
        m_framebuffer[i + 2] = color.b; // B
        m_framebuffer[i + 3] = color.a; // A
    }
}

void SoftwareRasterizer::setPixel(int x, int y, const Color& color) {
    if (x < 0 || x >= m_width || y < 0 || y >= m_height) return;
    
    int index = (y * m_width + x) * 4;
    m_framebuffer[index] = color.r;
    m_framebuffer[index + 1] = color.g;
    m_framebuffer[index + 2] = color.b;
    m_framebuffer[index + 3] = color.a;
}

void SoftwareRasterizer::drawLine(const Point& p0, const Point& p1, const Color& color) {
    // Bresenham算法
    if (std::abs(p1.y - p0.y) < std::abs(p1.x - p0.x)) {
        if (p0.x > p1.x) {
            drawLineLow(p1, p0, color);
        } else {
            drawLineLow(p0, p1, color);
        }
    } else {
        if (p0.y > p1.y) {
            drawLineHigh(p1, p0, color);
        } else {
            drawLineHigh(p0, p1, color);
        }
    }
}

void SoftwareRasterizer::drawLineLow(const Point& p0, const Point& p1, const Color& color) {
    int dx = p1.x - p0.x;
    int dy = p1.y - p0.y;
    int yi = 1;
    
    if (dy < 0) {
        yi = -1;
        dy = -dy;
    }
    
    int D = 2 * dy - dx;
    int y = p0.y;
    
    for (int x = p0.x; x <= p1.x; x++) {
        setPixel(x, y, color);
        if (D > 0) {
            y += yi;
            D -= 2 * dx;
        }
        D += 2 * dy;
    }
}

void SoftwareRasterizer::drawLineHigh(const Point& p0, const Point& p1, const Color& color) {
    int dx = p1.x - p0.x;
    int dy = p1.y - p0.y;
    int xi = 1;
    
    if (dx < 0) {
        xi = -1;
        dx = -dx;
    }
    
    int D = 2 * dx - dy;
    int x = p0.x;
    
    for (int y = p0.y; y <= p1.y; y++) {
        setPixel(x, y, color);
        if (D > 0) {
            x += xi;
            D -= 2 * dy;
        }
        D += 2 * dx;
    }
}

void SoftwareRasterizer::edgeFunction(const Point& a, const Point& b, const Point& p, float& result) {
    result = (p.x - a.x) * (b.y - a.y) - (p.y - a.y) * (b.x - a.x);
}

void SoftwareRasterizer::drawTriangle(const Triangle& triangle) {
    // 计算三角形的边界框
    int minX = std::min({triangle.v0.x, triangle.v1.x, triangle.v2.x});
    int maxX = std::max({triangle.v0.x, triangle.v1.x, triangle.v2.x});
    int minY = std::min({triangle.v0.y, triangle.v1.y, triangle.v2.y});
    int maxY = std::max({triangle.v0.y, triangle.v1.y, triangle.v2.y});
    
    // 裁剪到屏幕范围
    minX = std::max(minX, 0);
    maxX = std::min(maxX, m_width - 1);
    minY = std::max(minY, 0);
    maxY = std::min(maxY, m_height - 1);
    
    // 遍历边界框内的每个像素
    for (int y = minY; y <= maxY; y++) {
        for (int x = minX; x <= maxX; x++) {
            Point p(x, y);
            
            float w0, w1, w2;
            edgeFunction(triangle.v1, triangle.v2, p, w0);
            edgeFunction(triangle.v2, triangle.v0, p, w1);
            edgeFunction(triangle.v0, triangle.v1, p, w2);
            
            // 检查像素是否在三角形内
            if (w0 >= 0 && w1 >= 0 && w2 >= 0) {
                setPixel(x, y, triangle.color);
            }
        }
    }
}

void SoftwareRasterizer::drawCircle(const Point& center, int radius, const Color& color) {
    // 中点圆算法
    int x = 0;
    int y = radius;
    int d = 3 - 2 * radius;
    
    auto drawCirclePoints = [&](int x, int y) {
        setPixel(center.x + x, center.y + y, color);
        setPixel(center.x - x, center.y + y, color);
        setPixel(center.x + x, center.y - y, color);
        setPixel(center.x - x, center.y - y, color);
        setPixel(center.x + y, center.y + x, color);
        setPixel(center.x - y, center.y + x, color);
        setPixel(center.x + y, center.y - x, color);
        setPixel(center.x - y, center.y - x, color);
    };
    
    drawCirclePoints(x, y);
    
    while (y >= x) {
        x++;
        if (d > 0) {
            y--;
            d = d + 4 * (x - y) + 10;
        } else {
            d = d + 4 * x + 6;
        }
        drawCirclePoints(x, y);
    }
}

2.3 图形输入设备处理

现代图形系统支持多种输入设备,包括鼠标、键盘、游戏手柄等。


// InputSystem.h
#ifndef INPUT_SYSTEM_H
#define INPUT_SYSTEM_H

#include <GLFW/glfw3.h>
#include <unordered_map>
#include <functional>
#include <vector>

class InputSystem {
public:
    enum KeyState {
        RELEASED = 0,
        PRESSED = 1,
        REPEAT = 2
    };
    
    struct MouseState {
        double x, y;
        double scrollX, scrollY;
        KeyState buttons[8]; // GLFW支持最多8个鼠标按钮
    };
    
    InputSystem(GLFWwindow* window);
    ~InputSystem();
    
    void update();
    
    KeyState getKey(int key) const;
    KeyState getMouseButton(int button) const;
    void getMousePosition(double& x, double& y) const;
    void getMouseScroll(double& x, double& y) const;
    
    void setKeyCallback(std::function<void(int, KeyState)> callback);
    void setMouseCallback(std::function<void(double, double)> callback);
    void setScrollCallback(std::function<void(double, double)> callback);
    
private:
    GLFWwindow* m_window;
    std::unordered_map<int, KeyState> m_keyStates;
    MouseState m_mouseState;
    
    std::function<void(int, KeyState)> m_keyCallback;
    std::function<void(double, double)> m_mouseCallback;
    std::function<void(double, double)> m_scrollCallback;
    
    static void keyCallbackWrapper(GLFWwindow* window, int key, int scancode, int action, int mods);
    static void mouseCallbackWrapper(GLFWwindow* window, double xpos, double ypos);
    static void scrollCallbackWrapper(GLFWwindow* window, double xoffset, double yoffset);
    static void mouseButtonCallbackWrapper(GLFWwindow* window, int button, int action, int mods);
    
    void keyCallback(int key, int action);
    void mouseCallback(double xpos, double ypos);
    void scrollCallback(double xoffset, double yoffset);
    void mouseButtonCallback(int button, int action);
};

#endif

// InputSystem.cpp
#include "InputSystem.h"
#include <iostream>

InputSystem::InputSystem(GLFWwindow* window) : m_window(window) {
    // 设置GLFW回调
    glfwSetKeyCallback(window, keyCallbackWrapper);
    glfwSetCursorPosCallback(window, mouseCallbackWrapper);
    glfwSetScrollCallback(window, scrollCallbackWrapper);
    glfwSetMouseButtonCallback(window, mouseButtonCallbackWrapper);
    
    // 设置用户指针,以便在静态回调中访问实例
    glfwSetWindowUserPointer(window, this);
    
    // 初始化鼠标状态
    m_mouseState.x = 0.0;
    m_mouseState.y = 0.0;
    m_mouseState.scrollX = 0.0;
    m_mouseState.scrollY = 0.0;
    
    for (int i = 0; i < 8; i++) {
        m_mouseState.buttons[i] = RELEASED;
    }
}

InputSystem::~InputSystem() {
    // 移除回调
    glfwSetKeyCallback(m_window, nullptr);
    glfwSetCursorPosCallback(m_window, nullptr);
    glfwSetScrollCallback(m_window, nullptr);
    glfwSetMouseButtonCallback(m_window, nullptr);
}

void InputSystem::update() {
    // 重置鼠标滚轮值(每帧更新)
    m_mouseState.scrollX = 0.0;
    m_mouseState.scrollY = 0.0;
    
    glfwPollEvents();
}

InputSystem::KeyState InputSystem::getKey(int key) const {
    auto it = m_keyStates.find(key);
    if (it != m_keyStates.end()) {
        return it->second;
    }
    return RELEASED;
}

InputSystem::KeyState InputSystem::getMouseButton(int button) const {
    if (button >= 0 && button < 8) {
        return m_mouseState.buttons[button];
    }
    return RELEASED;
}

void InputSystem::getMousePosition(double& x, double& y) const {
    x = m_mouseState.x;
    y = m_mouseState.y;
}

void InputSystem::getMouseScroll(double& x, double& y) const {
    x = m_mouseState.scrollX;
    y = m_mouseState.scrollY;
}

void InputSystem::setKeyCallback(std::function<void(int, KeyState)> callback) {
    m_keyCallback = callback;
}

void InputSystem::setMouseCallback(std::function<void(double, double)> callback) {
    m_mouseCallback = callback;
}

void InputSystem::setScrollCallback(std::function<void(double, double)> callback) {
    m_scrollCallback = callback;
}

// 静态回调包装器
void InputSystem::keyCallbackWrapper(GLFWwindow* window, int key, int scancode, int action, int mods) {
    InputSystem* inputSystem = static_cast<InputSystem*>(glfwGetWindowUserPointer(window));
    if (inputSystem) {
        inputSystem->keyCallback(key, action);
    }
}

void InputSystem::mouseCallbackWrapper(GLFWwindow* window, double xpos, double ypos) {
    InputSystem* inputSystem = static_cast<InputSystem*>(glfwGetWindowUserPointer(window));
    if (inputSystem) {
        inputSystem->mouseCallback(xpos, ypos);
    }
}

void InputSystem::scrollCallbackWrapper(GLFWwindow* window, double xoffset, double yoffset) {
    InputSystem* inputSystem = static_cast<InputSystem*>(glfwGetWindowUserPointer(window));
    if (inputSystem) {
        inputSystem->scrollCallback(xoffset, yoffset);
    }
}

void InputSystem::mouseButtonCallbackWrapper(GLFWwindow* window, int button, int action, int mods) {
    InputSystem* inputSystem = static_cast<InputSystem*>(glfwGetWindowUserPointer(window));
    if (inputSystem) {
        inputSystem->mouseButtonCallback(button, action);
    }
}

// 实例回调方法
void InputSystem::keyCallback(int key, int action) {
    KeyState state;
    switch (action) {
        case GLFW_PRESS:
            state = PRESSED;
            break;
        case GLFW_RELEASE:
            state = RELEASED;
            break;
        case GLFW_REPEAT:
            state = REPEAT;
            break;
        default:
            return;
    }
    
    m_keyStates[key] = state;
    
    if (m_keyCallback) {
        m_keyCallback(key, state);
    }
}

void InputSystem::mouseCallback(double xpos, double ypos) {
    m_mouseState.x = xpos;
    m_mouseState.y = ypos;
    
    if (m_mouseCallback) {
        m_mouseCallback(xpos, ypos);
    }
}

void InputSystem::scrollCallback(double xoffset, double yoffset) {
    m_mouseState.scrollX = xoffset;
    m_mouseState.scrollY = yoffset;
    
    if (m_scrollCallback) {
        m_scrollCallback(xoffset, yoffset);
    }
}

void InputSystem::mouseButtonCallback(int button, int action) {
    if (button >= 0 && button < 8) {
        KeyState state = (action == GLFW_PRESS) ? PRESSED : RELEASED;
        m_mouseState.buttons[button] = state;
    }
}

2.4 OpenGL图形API详解

OpenGL是跨平台的图形API,提供硬件加速的2D和3D图形渲染。


// OpenGLRenderer.h
#ifndef OPENGL_RENDERER_H
#define OPENGL_RENDERER_H

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <vector>
#include <string>

class OpenGLRenderer {
public:
    struct Vertex {
        glm::vec3 position;
        glm::vec3 color;
        glm::vec2 texCoord;
        
        Vertex(glm::vec3 pos, glm::vec3 col, glm::vec2 tex) 
            : position(pos), color(col), texCoord(tex) {}
    };
    
    OpenGLRenderer();
    ~OpenGLRenderer();
    
    bool initialize(int width, int height);
    void render();
    void cleanup();
    
    void createShaderProgram(const std::string& vertexSource, const std::string& fragmentSource);
    void createBuffer(const std::vector<Vertex>& vertices, const std::vector<unsigned int>& indices);
    
    void setClearColor(float r, float g, float b, float a);
    void setViewMatrix(const glm::mat4& view);
    void setProjectionMatrix(const glm::mat4& projection);
    
private:
    GLFWwindow* m_window;
    unsigned int m_shaderProgram;
    unsigned int m_VAO, m_VBO, m_EBO;
    
    glm::mat4 m_view;
    glm::mat4 m_projection;
    glm::vec4 m_clearColor;
    
    int m_width, m_height;
    
    void checkCompileErrors(unsigned int shader, const std::string& type);
};

#endif

// OpenGLRenderer.cpp
#include "OpenGLRenderer.h"
#include <iostream>
#include <fstream>
#include <sstream>

OpenGLRenderer::OpenGLRenderer() 
    : m_window(nullptr), m_shaderProgram(0)
    , m_VAO(0), m_VBO(0), m_EBO(0)
    , m_clearColor(0.2f, 0.3f, 0.3f, 1.0f)
    , m_width(800), m_height(600) {
    
    m_view = glm::mat4(1.0f);
    m_projection = glm::mat4(1.0f);
}

OpenGLRenderer::~OpenGLRenderer() {
    cleanup();
}

bool OpenGLRenderer::initialize(int width, int height) {
    m_width = width;
    m_height = height;
    
    if (!glfwInit()) {
        std::cerr << "GLFW初始化失败!" << std::endl;
        return false;
    }
    
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    
    m_window = glfwCreateWindow(width, height, "OpenGL渲染器", nullptr, nullptr);
    if (!m_window) {
        std::cerr << "创建窗口失败!" << std::endl;
        glfwTerminate();
        return false;
    }
    
    glfwMakeContextCurrent(m_window);
    
    if (glewInit() != GLEW_OK) {
        std::cerr << "GLEW初始化失败!" << std::endl;
        return false;
    }
    
    glEnable(GL_DEPTH_TEST);
    glViewport(0, 0, width, height);
    
    // 设置默认投影矩阵
    m_projection = glm::perspective(glm::radians(45.0f), (float)width / (float)height, 0.1f, 100.0f);
    
    return true;
}

void OpenGLRenderer::createShaderProgram(const std::string& vertexSource, const std::string& fragmentSource) {
    const char* vShaderCode = vertexSource.c_str();
    const char* fShaderCode = fragmentSource.c_str();
    
    // 顶点着色器
    unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vShaderCode, NULL);
    glCompileShader(vertexShader);
    checkCompileErrors(vertexShader, "VERTEX");
    
    // 片段着色器
    unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fShaderCode, NULL);
    glCompileShader(fragmentShader);
    checkCompileErrors(fragmentShader, "FRAGMENT");
    
    // 着色器程序
    m_shaderProgram = glCreateProgram();
    glAttachShader(m_shaderProgram, vertexShader);
    glAttachShader(m_shaderProgram, fragmentShader);
    glLinkProgram(m_shaderProgram);
    checkCompileErrors(m_shaderProgram, "PROGRAM");
    
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);
}

void OpenGLRenderer::createBuffer(const std::vector<Vertex>& vertices, const std::vector<unsigned int>& indices) {
    glGenVertexArrays(1, &m_VAO);
    glGenBuffers(1, &m_VBO);
    glGenBuffers(1, &m_EBO);
    
    glBindVertexArray(m_VAO);
    
    glBindBuffer(GL_ARRAY_BUFFER, m_VBO);
    glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), vertices.data(), GL_STATIC_DRAW);
    
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), indices.data(), GL_STATIC_DRAW);
    
    // 位置属性
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0);
    glEnableVertexAttribArray(0);
    
    // 颜色属性
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, color));
    glEnableVertexAttribArray(1);
    
    // 纹理坐标属性
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, texCoord));
    glEnableVertexAttribArray(2);
    
    glBindVertexArray(0);
}

void OpenGLRenderer::setClearColor(float r, float g, float b, float a) {
    m_clearColor = glm::vec4(r, g, b, a);
}

void OpenGLRenderer::setViewMatrix(const glm::mat4& view) {
    m_view = view;
}

void OpenGLRenderer::setProjectionMatrix(const glm::mat4& projection) {
    m_projection = projection;
}

void OpenGLRenderer::render() {
    glClearColor(m_clearColor.r, m_clearColor.g, m_clearColor.b, m_clearColor.a);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
    glUseProgram(m_shaderProgram);
    
    // 设置变换矩阵
    GLint viewLoc = glGetUniformLocation(m_shaderProgram, "view");
    GLint projLoc = glGetUniformLocation(m_shaderProgram, "projection");
    
    glUniformMatrix4fv(viewLoc, 1, GL_FALSE, &m_view[0][0]);
    glUniformMatrix4fv(projLoc, 1, GL_FALSE, &m_projection[0][0]);
    
    // 渲染几何体
    glBindVertexArray(m_VAO);
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
    glBindVertexArray(0);
    
    glfwSwapBuffers(m_window);
}

void OpenGLRenderer::checkCompileErrors(unsigned int shader, const std::string& type) {
    int success;
    char infoLog[1024];
    
    if (type != "PROGRAM") {
        glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
        if (!success) {
            glGetShaderInfoLog(shader, 1024, NULL, infoLog);
            std::cerr << "着色器编译错误: " << type << "
" << infoLog << std::endl;
        }
    } else {
        glGetProgramiv(shader, GL_LINK_STATUS, &success);
        if (!success) {
            glGetProgramInfoLog(shader, 1024, NULL, infoLog);
            std::cerr << "程序链接错误: " << type << "
" << infoLog << std::endl;
        }
    }
}

void OpenGLRenderer::cleanup() {
    if (m_shaderProgram) glDeleteProgram(m_shaderProgram);
    if (m_VAO) glDeleteVertexArrays(1, &m_VAO);
    if (m_VBO) glDeleteBuffers(1, &m_VBO);
    if (m_EBO) glDeleteBuffers(1, &m_EBO);
    
    if (m_window) {
        glfwDestroyWindow(m_window);
        glfwTerminate();
    }
}

2.5 综合演示程序


// main.cpp - 图形系统综合演示
#include <iostream>
#include <thread>
#include <chrono>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>

#include "DisplaySystem.h"
#include "SoftwareRasterizer.h"
#include "InputSystem.h"
#include "OpenGLRenderer.h"

void demonstrateDisplaySystems() {
    std::cout << "=== 显示系统模拟演示 ===" << std::endl;
    
    DisplaySystem crtDisplay;
    if (crtDisplay.initialize(800, 600, DisplaySystem::CRT_SIMULATION)) {
        for (int i = 0; i < 180; i++) { // 3秒演示
            crtDisplay.update();
            crtDisplay.render();
            std::this_thread::sleep_for(std::chrono::milliseconds(16));
        }
        crtDisplay.cleanup();
    }
}

void demonstrateSoftwareRasterizer() {
    std::cout << "=== 软件光栅化演示 ===" << std::endl;
    
    SoftwareRasterizer rasterizer(800, 600);
    
    // 绘制一些基本图形
    rasterizer.clear(Color(0, 0, 0, 255));
    
    // 绘制线条
    rasterizer.drawLine(Point(100, 100), Point(700, 100), Color(255, 0, 0, 255));
    rasterizer.drawLine(Point(100, 500), Point(700, 500), Color(0, 255, 0, 255));
    
    // 绘制三角形
    Triangle tri(Point(400, 200), Point(300, 400), Point(500, 400), Color(0, 0, 255, 255));
    rasterizer.drawTriangle(tri);
    
    // 绘制圆形
    rasterizer.drawCircle(Point(400, 300), 100, Color(255, 255, 0, 255));
    
    std::cout << "软件光栅化完成,输出尺寸: " << rasterizer.getWidth() << "x" << rasterizer.getHeight() << std::endl;
}

void demonstrateOpenGLRendering() {
    std::cout << "=== OpenGL渲染演示 ===" << std::endl;
    
    OpenGLRenderer renderer;
    if (!renderer.initialize(800, 600)) {
        return;
    }
    
    // 创建着色器
    std::string vertexShader = R"(
        #version 330 core
        layout (location = 0) in vec3 aPos;
        layout (location = 1) in vec3 aColor;
        layout (location = 2) in vec2 aTexCoord;
        
        out vec3 ourColor;
        out vec2 TexCoord;
        
        uniform mat4 view;
        uniform mat4 projection;
        
        void main() {
            gl_Position = projection * view * vec4(aPos, 1.0);
            ourColor = aColor;
            TexCoord = aTexCoord;
        }
    )";
    
    std::string fragmentShader = R"(
        #version 330 core
        out vec4 FragColor;
        
        in vec3 ourColor;
        in vec2 TexCoord;
        
        void main() {
            FragColor = vec4(ourColor, 1.0);
        }
    )";
    
    renderer.createShaderProgram(vertexShader, fragmentShader);
    
    // 创建顶点数据
    std::vector<OpenGLRenderer::Vertex> vertices = {
        OpenGLRenderer::Vertex(glm::vec3(-0.5f, -0.5f, 0.0f), glm::vec3(1.0f, 0.0f, 0.0f), glm::vec2(0.0f, 0.0f)),
        OpenGLRenderer::Vertex(glm::vec3(0.5f, -0.5f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f), glm::vec2(1.0f, 0.0f)),
        OpenGLRenderer::Vertex(glm::vec3(0.5f, 0.5f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f), glm::vec2(1.0f, 1.0f)),
        OpenGLRenderer::Vertex(glm::vec3(-0.5f, 0.5f, 0.0f), glm::vec3(1.0f, 1.0f, 0.0f), glm::vec2(0.0f, 1.0f))
    };
    
    std::vector<unsigned int> indices = {
        0, 1, 2,
        2, 3, 0
    };
    
    renderer.createBuffer(vertices, indices);
    
    // 设置相机
    glm::mat4 view = glm::lookAt(
        glm::vec3(0.0f, 0.0f, 3.0f),
        glm::vec3(0.0f, 0.0f, 0.0f),
        glm::vec3(0.0f, 1.0f, 0.0f)
    );
    renderer.setViewMatrix(view);
    
    // 渲染循环
    auto lastTime = std::chrono::high_resolution_clock::now();
    float rotation = 0.0f;
    
    for (int i = 0; i < 180; i++) { // 3秒演示
        auto currentTime = std::chrono::high_resolution_clock::now();
        float deltaTime = std::chrono::duration<float>(currentTime - lastTime).count();
        lastTime = currentTime;
        
        rotation += deltaTime * 50.0f;
        
        // 更新视图矩阵(旋转)
        glm::mat4 rotatedView = glm::rotate(view, glm::radians(rotation), glm::vec3(0.0f, 1.0f, 0.0f));
        renderer.setViewMatrix(rotatedView);
        
        renderer.render();
        std::this_thread::sleep_for(std::chrono::milliseconds(16));
    }
    
    renderer.cleanup();
}

void demonstrateInputSystem() {
    std::cout << "=== 输入系统演示 ===" << std::endl;
    
    GLFWwindow* window;
    if (!glfwInit()) return;
    
    window = glfwCreateWindow(800, 600, "输入系统测试", nullptr, nullptr);
    if (!window) {
        glfwTerminate();
        return;
    }
    
    glfwMakeContextCurrent(window);
    
    InputSystem inputSystem(window);
    
    // 设置输入回调
    inputSystem.setKeyCallback([](int key, InputSystem::KeyState state) {
        if (state == InputSystem::PRESSED) {
            std::cout << "按键按下: " << key << std::endl;
        }
    });
    
    inputSystem.setMouseCallback([](double x, double y) {
        // 可以在这里处理鼠标移动
    });
    
    inputSystem.setScrollCallback([](double x, double y) {
        std::cout << "鼠标滚轮: " << x << ", " << y << std::endl;
    });
    
    auto startTime = std::chrono::high_resolution_clock::now();
    
    while (!glfwWindowShouldClose(window)) {
        auto currentTime = std::chrono::high_resolution_clock::now();
        float elapsed = std::chrono::duration<float>(currentTime - startTime).count();
        
        if (elapsed >= 5.0f) { // 演示5秒
            break;
        }
        
        inputSystem.update();
        
        // 检查特定按键
        if (inputSystem.getKey(GLFW_KEY_SPACE) == InputSystem::PRESSED) {
            std::cout << "空格键被按下!" << std::endl;
        }
        
        if (inputSystem.getMouseButton(GLFW_MOUSE_BUTTON_LEFT) == InputSystem::PRESSED) {
            double x, y;
            inputSystem.getMousePosition(x, y);
            std::cout << "鼠标左键点击位置: " << x << ", " << y << std::endl;
        }
        
        glfwSwapBuffers(window);
        std::this_thread::sleep_for(std::chrono::milliseconds(16));
    }
    
    glfwDestroyWindow(window);
    glfwTerminate();
}

int main() {
    std::cout << "图形系统架构与技术实现演示程序" << std::endl;
    std::cout << "=============================" << std::endl;
    
    // 演示显示系统
    demonstrateDisplaySystems();
    
    // 演示软件光栅化
    demonstrateSoftwareRasterizer();
    
    // 演示OpenGL渲染
    demonstrateOpenGLRendering();
    
    // 演示输入系统
    demonstrateInputSystem();
    
    std::cout << "所有演示完成!" << std::endl;
    std::cout << "按任意键退出..." << std::endl;
    std::cin.get();
    
    return 0;
}

2.10 技术总结

现代图形系统是硬件和软件紧密结合的复杂系统。关键要点包括:

显示技术:理解不同显示设备的特性对于优化图形应用很重要光栅化:软件光栅化帮助理解图形管线的基本原理输入处理:高效的输入系统是交互式应用的基础图形API:OpenGL等API提供了硬件加速的图形渲染能力

通过理解这些基础组件,开发者能够创建高效、响应迅速的图形应用程序。现代图形系统继续向更高分辨率、更快刷新率和更真实的视觉效果发展,为虚拟现实、游戏和科学可视化等领域提供强大的支持。

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容