第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






![在苹果iPhone手机上编写ios越狱插件deb[超简单] - 鹿快](https://img.lukuai.com/blogimg/20251123/23f740f048644a198a64e73eeaa43e60.jpg)













暂无评论内容