gpt4 book ai didi

c++ - 着色器和纹理坐标问题

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:06:58 25 4
gpt4 key购买 nike

我有一个我正在尝试使用的着色器,但我遇到了一个我无法解决的问题,因为我对 glsl 的了解有限。我使用纹理作为蒙版并调试此问题我只是使用此纹理像素颜色作为 gl_FragColor,我将发布一些图像以显示它的外观和应该的外观。

图片链接; https://imgur.com/EBt2vbL

这似乎与 gl_TexCoord[0].xy 的坐标没有得到溶解纹理的正确坐标有关

主要.cpp

#include "Engine.h"

#include <stdio.h>
#include <iostream>
#include <windows.h>

int main(int argc, char *argv[])
{
try
{
Engine game;
game.Run();
}
catch (std::exception& err)
{
std::cout << "\nException: " << err.what() << std::endl;
}

return 0;
}

引擎.h

#pragma once

#include <SFML/System.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include <SFML/Audio.hpp>
#include <SFML/Network.hpp>

#include <vector>
#include <iostream>

class Engine
{
public:
Engine();

void Run();
void HandleEvents(sf::Time deltaTime);
void Update(sf::Time deltaTime);
void BuildVertices();
void Draw();

private:
bool running;
bool hasFocus;
bool fullScreen;


sf::RenderWindow mainWindow;
sf::Time deltaTime;
sf::Event event;

sf::Vector2i screenResolution;
sf::Vector2i mousePosition;

sf::VertexArray vertices;
sf::Vertex vertex;
sf::Shader dissolveShader;
sf::Texture dissolveTexture;
sf::RenderStates renderState;
float dissolveValue;

sf::Texture objectSpriteSheetTexture;
};

引擎.cpp

#include "Engine.h"

static const sf::Time TimePerFrame = sf::seconds(1.f / 60.f);

Engine::Engine()
: hasFocus(true)
, fullScreen(fullScreen)
, running(false)
, dissolveValue(1.0f)
, vertices(sf::Quads)
{

mainWindow.create(sf::VideoMode(640, 480), "Test", sf::Style::Titlebar);
mainWindow.setPosition(sf::Vector2i(0, 0));
screenResolution.x = 640;
screenResolution.y = 480;

// 512x512 sheet, each sprite is 128x128
if (!objectSpriteSheetTexture.loadFromFile("ObjectSheet.png"))
std::cout << "failed to load ObjectSheet.png" << std::endl;

if (!dissolveTexture.loadFromFile("DissolveTexture.png"))
std::cout << "failed to load DissolveTexture.png" << std::endl;

if (!dissolveShader.loadFromFile("DissolveShader.frag", sf::Shader::Fragment))
{
std::cout << "failed to load DissolveShader.frag" << std::endl;
}

dissolveShader.setUniform("sourceTexture", sf::Shader::CurrentTexture);
dissolveShader.setUniform("dissolveTexture", dissolveTexture);

renderState.shader = &dissolveShader;
renderState.texture = &objectSpriteSheetTexture;
}



void Engine::Run()
{
// main loop
sf::Clock clock;
sf::Time timeSinceLastUpdate = sf::Time::Zero;

sf::Time elapsedTime;

running = true;

while(running)
{
elapsedTime = clock.restart();
timeSinceLastUpdate += elapsedTime;

HandleEvents(TimePerFrame);
while(timeSinceLastUpdate > TimePerFrame)
{
timeSinceLastUpdate -= TimePerFrame;
Update(TimePerFrame);
}

BuildVertices();
Draw();
}
}


void Engine::HandleEvents(sf::Time deltaTime)
{
mousePosition = sf::Mouse::getPosition(mainWindow);

while(mainWindow.pollEvent(event))
{
if(event.type == sf::Event::Closed)
mainWindow.close();

if (event.type == sf::Event::KeyPressed)
{
if (event.key.code == sf::Keyboard::Escape)
{
running = false;
}
}
}
}

void Engine::Update(sf::Time deltaTime)
{
}

void Engine::BuildVertices()
{
vertices.clear();

int frameSize = 128;

sf::Vector2i objectPosition(100, 100);
sf::Vector2i spriteSheetTextureCoordinates(0, 128);

vertex.position.x = objectPosition.x;
vertex.position.y = objectPosition.y;
vertex.texCoords.x = spriteSheetTextureCoordinates.x;
vertex.texCoords.y = spriteSheetTextureCoordinates.y;
vertices.append(vertex);

vertex.position.x = objectPosition.x + frameSize;
vertex.position.y = objectPosition.y;
vertex.texCoords.x = spriteSheetTextureCoordinates.x + frameSize;
vertex.texCoords.y = spriteSheetTextureCoordinates.y;
vertices.append(vertex);

vertex.position.x = objectPosition.x + frameSize;
vertex.position.y = objectPosition.y + frameSize;
vertex.texCoords.x = spriteSheetTextureCoordinates.x + frameSize;
vertex.texCoords.y = spriteSheetTextureCoordinates.y + frameSize;
vertices.append(vertex);

vertex.position.x = objectPosition.x;
vertex.position.y = objectPosition.y + frameSize;
vertex.texCoords.x = spriteSheetTextureCoordinates.x;
vertex.texCoords.y = spriteSheetTextureCoordinates.y + frameSize;
vertices.append(vertex);
}

void Engine::Draw()
{
mainWindow.clear(sf::Color::Black);

dissolveShader.setUniform("dissolveValue", dissolveValue);

mainWindow.draw(vertices, renderState);

mainWindow.display();
}

顶点着色器是由 sfml 处理的标准 channel 。


片段着色器;

#version 130

// used as the mask to determine if a pixel of the source texture should be drawn, 128x128
uniform sampler2D dissolveTexture;

// the texture of the object i'm drawing, a 128x128 part of a 512x512 sprite sheet
uniform sampler2D sourceTexture;

// set to 1.0 for debug
uniform float dissolveValue;

void main( void )
{
vec4 sourceColor = texture2D(sourceTexture, gl_TexCoord[0].xy);
vec4 maskColor = texture2D(dissolveTexture, gl_TexCoord[0].xy);

if(maskColor.r <= dissolveValue)
{
// it would return the source pixel color here one the issue is solved
// gl_FragColor = sourceColor;

// debuging, so returning the mask textures pixel color
gl_FragColor = maskColor;
}
else
{
gl_FragColor = sourceColor;
}
}

我可能忽略了一些简单的事情,所以如果有人能指出正确的方向,我将不胜感激,谢谢!

最佳答案

纹理坐标,用于 GLSL 函数 texture (formerly texture2D)范围从 0.0 到 1.0,其中 (0.0, 0.0) 通常是纹理图像的左下角,(1.0, 1.0) 是纹理图像的右上角。

但是,SFML 库会根据当前纹理 (sf::Shader::CurrentTexture) 的大小来缩放纹理坐标。这意味着纹理坐标必须设置在当前纹理大小的范围内:

这意味着您必须像这样设置纹理坐标:

void Engine::BuildVertices()
{
vertices.clear();

int frameSize = 128;
sf::Vector2i objectPosition(100, 100);

sf::Vector2i texSize(512, 512);

vertex.position = sf::Vector2f(objectPosition.x, objectPosition.y);
vertex.texCoords = sf::Vector2f(0.0f, 0.0f);
vertices.append(vertex);

vertex.position = sf::Vector2f(objectPosition.x + frameSize, objectPosition.y);
vertex.texCoords = sf::Vector2f(texSize.x, 0.0f);
vertices.append(vertex);

vertex.position = sf::Vector2f(objectPosition.x + frameSize, objectPosition.y + frameSize);
vertex.texCoords = sf::Vector2f(texSize.x, texSize.y);
vertices.append(vertex);

vertex.position = sf::Vector2f(objectPosition.x, objectPosition.y + frameSize);
vertex.texCoords = sf::Vector2f(0.0f, texSize.y);
vertices.append(vertex);
}


你有一个大小为 128*128 的 mask 纹理,你有一个大小为 512*512 的平铺 Sprite (4*4 block )。我建议向片段着色器添加一个纹理坐标偏移统一 (texOffset) 和一个纹理比例统一 (texScale),允许选择纹理的一个瓦片:

#version 130

uniform sampler2D dissolveTexture;
uniform sampler2D sourceTexture;
uniform float dissolveValue;
uniform vec2 texScale;
uniform vec2 texOffset;

void main( void )
{
vec4 sourceColor = texture2D(sourceTexture, texOffset+texScale*gl_TexCoord[0].xy);
vec4 maskColor = texture2D(dissolveTexture, gl_TexCoord[0].xy);

gl_FragColor = mix( sourceColor, maskColor, step(maskColor.r, dissolveValue) );
}

您必须在函数 Draw 中设置制服。比例由图 block 行数和列数的倒数给出。偏移量是瓦片的索引乘以比例因子:

void Engine::Draw()
{
mainWindow.clear(sf::Color::Black);

dissolveValue = 0.5f;
dissolveShader.setUniform("dissolveValue", dissolveValue);

float scale_x = 1.0f/4.0f;
float scale_y = 1.0f/4.0f;
int i_x = 1; // column of tile (form 0 to 3)
int i_y = 2; // row of tile (form 0 to 3)

dissolveShader.setUniform("texScale", sf::Glsl::Vec2(scale_x, scale_y));
dissolveShader.setUniform("texOffset", sf::Glsl::Vec2(i_x*scale_x, i_y*scale_y));

mainWindow.draw(vertices, renderState);

mainWindow.display();
}

关于c++ - 着色器和纹理坐标问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48312086/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com