为什么是红整型¶
Red:单通道 32 INT,更多的实体容纳范围
Framebuffer¶
enum class FramebufferTextureFormat
{
None = 0,
// Color
RGBA8,
//新的
RED_INTEGER,
// Depth/stencil
DEPTH24STENCIL8,
// Defaults
Depth = DEPTH24STENCIL8
};
virtual int ReadPixel(uint32_t attachmentIndex, int x, int y) = 0;
OpenGL对应实现¶
主要是根据下面这个函数,取样拿到internalFormat
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, internalFormat, width, height, GL_FALSE);
代码
static void AttachColorTexture(uint32_t id, int samples, GLenum internalFormat, GLenum format, uint32_t width, uint32_t height, int index)
{
bool multisampled = samples > 1;
if (multisampled)
{
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, internalFormat, width, height, GL_FALSE);
}
else
{
glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, format, GL_UNSIGNED_BYTE, nullptr);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + index, TextureTarget(multisampled), id, 0);
}
static void AttachDepthTexture(uint32_t id, int samples, GLenum format, GLenum attachmentType, uint32_t width, uint32_t height)
{
bool multisampled = samples > 1;
if (multisampled)
{
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, format, width, height, GL_FALSE);
}
else
{
glTexStorage2D(GL_TEXTURE_2D, 1, format, width, height);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
glFramebufferTexture2D(GL_FRAMEBUFFER, attachmentType, TextureTarget(multisampled), id, 0);
}
单独处理¶
case FramebufferTextureFormat::RED_INTEGER:
Utils::AttachColorTexture(m_ColorAttachments[i], m_Specification.Samples, GL_R32I, GL_RED_INTEGER, m_Specification.Width, m_Specification.Height, i);
ReadPixel¶
传入坐标,读对应的缓冲区附件,然后读对应的像素点
glReadPixels(x, y, 1, 1, GL_RED_INTEGER, GL_INT, &pixelData);
: 这个函数调用从帧缓冲对象中读取像素数据。参数如下:
- x
和 y
:指定要读取的像素的坐标。
- 1
和 1
:指定要读取的像素区域的宽度和高度,这里是单个像素。
- GL_RED_INTEGER
:指定要读取的像素数据的格式,这里是红色通道的整型数据。
- GL_INT
:指定像素数据的数据类型,这里是整型。
- &pixelData
:指向存储读取数据的变量的指针。
函数返回读取到的像素数据id
int OpenGLFramebuffer::ReadPixel(uint32_t attachmentIndex, int x, int y)
{
CORE_DEBUG_ASSERT(attachmentIndex < m_ColorAttachments.size());
glReadBuffer(GL_COLOR_ATTACHMENT0 + attachmentIndex);
int pixelData;
glReadPixels(x, y, 1, 1, GL_RED_INTEGER, GL_INT, &pixelData);
return pixelData;
}
EditorLayer¶
设置bound
glm::vec2 m_ViewportBounds[2];
auto [mx, my] = ImGui::GetMousePos();
mx -= m_ViewportBounds[0].x;
my -= m_ViewportBounds[0].y;
glm::vec2 viewportSize = m_ViewportBounds[1] - m_ViewportBounds[0];
my = viewportSize.y - my;
int mouseX = (int)mx;
int mouseY = (int)my;
if (mouseX >= 0 && mouseY >= 0 && mouseX < (int)viewportSize.x && mouseY < (int)viewportSize.y)
{
int pixelData = m_Framebuffer->ReadPixel(1, mouseX, mouseY);
CORE_DEBUG_WARN("Pixel data = {0}", pixelData);
}
imgui¶
update:
//获取光标位置
auto viewportOffset = ImGui::GetCursorPos(); // Includes tab bar
//设置边界
auto windowSize = ImGui::GetWindowSize();
ImVec2 minBound = ImGui::GetWindowPos();
minBound.x += viewportOffset.x;
minBound.y += viewportOffset.y;
ImVec2 maxBound = { minBound.x + windowSize.x, minBound.y + windowSize.y };
m_ViewportBounds[0] = { minBound.x, minBound.y };
m_ViewportBounds[1] = { maxBound.x, maxBound.y };
GLSL¶
我们这里用color2来表示
layout(location = 0) out vec4 color;
layout(location = 1) out int color2;
void main()
{
...
color2 = 50;
}