首先确保你有工程了, 如何创建工程
颜色缓冲区(Color Buffer)是什么?
是图形渲染中的一个概念,也就是最终渲染到屏幕上的图像的颜色信息
渲染管线的最后阶段(片段着色器)会为每个屏幕上的像素计算颜色,并将这些颜色值写入颜色缓冲区
颜色缓冲区可以包含红、绿、蓝和透明度(RGBA)等颜色分量
结合一下:
我们用OpenGL的Texture当作Buffer,那Texture 数据存储的是 unsgined char*
数组
用1维数组如何表示2维的的矩阵呢?其实就是一个简单对应关系
- 比如:
2x2的缓冲区大小,每个缓冲区里面有三个颜色值RGB,范围是char 0-255 - 表示为:
p1 p2
p3 p4 - 数据存储为:
r(p1) g(p1) b(p1) r(p2) g(p2) b(p2) r(p3) g(p3) b(p3) r(p4) g(p4) b(p4)
也就是有 223 (长x宽x颜色个数)的大小,换算成索引就是:index = (x+y*w)*3
结合到工程中
1.定义一个class 叫做 CPURenderer
a)包含颜色缓冲数组
b)构造函数根据图像的宽高复制(注意:不一定就是你窗口像素,最后会走视口变化自由缩放)
c)提供 Render 函数,用来做绘制
cpurenderer.h 中
class CPURenderer {
public:
//颜色缓冲
unsigned char* colorAttachment;
int colorLen;
CPURenderer(int w, int h)
{
colorLen = colorLen = w * h * 3;
colorAttachment = new unsigned char[colorLen];
}
void Render(float currentTime, float deltaTime) {
// do something ...
}
}
2.在main.cpp 中调用
a)定义cpu渲染器
b)调用Render接口内部做渲染
c)把cpu渲染器的颜色缓冲区数据传到OpenGL创建的Texture里面,用来绘制
// ... 省略
//定义cpu渲染器
CPURenderer* cpuRenderer;
int main() {
// ... 省略
//初始化cpu渲染器
cpuRenderer = new CPURenderer(WIN_WIDTH, WIN_HEIGHT);
float deltaTime = 0.0f;
float lastTime = 0.0f;
while (!glfwWindowShouldClose(window)) {
glfwPollEvents();
float currentTime = (float)glfwGetTime();
deltaTime = currentTime - lastTime;
lastTime = currentTime;
//调用Render接口内部做渲染
cpuRenderer->Render(currentTime, deltaTime);
draw();
glfwSwapBuffers(window);
}
// ... 省略
}
// ... 省略
void draw()
{
glClearColor(0.1f, 0.1f, 0.1f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shaderProgram);
glBindTexture(GL_TEXTURE_2D, colorTextureID);
//把cpu渲染器的颜色缓冲区数据传到OpenGL创建的Texture里面,用来绘制
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, WIN_WIDTH, WIN_HEIGHT, GL_RGB, GL_UNSIGNED_BYTE, cpuRenderer->colorAttachment);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}
// ... 省略
3.测试
在CpuRenderer 里面的draw方法设置像素颜色
cpurenderer.h 中
void Render(float currentTime, float deltaTime) {
//清除上一帧的颜色
clearColor();
for(int x=0; x<100; x++){
setColor(x,200, 255,0,0);
}
}
void setColor(int x, int y, float r, float g, float b) const {
int index = (x + y * viewport.w) * 3;
colorAttachment[index + 0] = r;
colorAttachment[index + 1] = g;
colorAttachment[index + 2] = b;
}
如果有红色的线,就完成了!
PS:为了之后方便一点,把Color 提出单独的类来,定义一些辅助函数
color.h
#ifndef _COLOR_H
#define _COLOR_H
#include<iostream>
struct Color {
unsigned char r;
unsigned char g;
unsigned char b;
Color() {
}
Color(
unsigned char red,
unsigned char green,
unsigned char blue)
:r(red), g(green), b(blue)
{
}
friend Color operator/ (const Color& l, float v) {
Color result;
result.r = (unsigned char)((float)l.r / v);
result.g = (unsigned char)((float)l.g / v);
result.b = (unsigned char)((float)l.b / v);
return result;
}
friend Color operator* (const Color& l, const Color& r) {
Color result;
result.r = (l.r * r.r) / 255;
result.g = (l.g * r.g) / 255;
result.b = (l.b * r.b) / 255;
return result;
}
static Color red;
static Color green;
static Color blue;
static Color white;
};
#endif
color.cpp
#include "color.h"
Color Color::red = Color(255, 0, 0);
Color Color::green = Color(0, 255, 0);
Color Color::blue = Color(0, 0, 255);
Color Color::white = Color(255, 255, 255);