我想在网格的每个实例上执行逐像素操作。我发现了一个名为gl_FragCoord的变量,但似乎它的坐标是SCREEN坐标。我想访问LOCAL坐标,以便我可以进行独立影响每个网格的更改。我想有坐标,例如(0.0,0.0)坐标是片段的左上角,(1.0,1.0)是右下角的坐标。
答案 0 :(得分:1)
您可以将视口作为制服传递,并通过视口W划分您的frag coord X,并通过视口H划分Y frag coord
答案 1 :(得分:0)
使用barycentric coordinates和其他顶点属性构建三角形局部坐标系:
#include <GL/glew.h>
#include <GL/freeglut.h>
#include <iostream>
#include <vector>
using namespace std;
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtx/transform.hpp>
using namespace glm;
void CheckStatus( GLuint obj )
{
GLint status = GL_FALSE;
if( glIsShader(obj) ) glGetShaderiv( obj, GL_COMPILE_STATUS, &status );
if( glIsProgram(obj) ) glGetProgramiv( obj, GL_LINK_STATUS, &status );
if( status == GL_TRUE ) return;
GLchar log[ 1 << 16 ] = { 0 };
if( glIsShader(obj) ) glGetShaderInfoLog( obj, sizeof(log), NULL, log );
if( glIsProgram(obj) ) glGetProgramInfoLog( obj, sizeof(log), NULL, log );
std::cerr << log << std::endl;
exit( -1 );
}
void AttachShader( GLuint program, GLenum type, const char* src )
{
GLuint shader = glCreateShader( type );
glShaderSource( shader, 1, &src, NULL );
glCompileShader( shader );
CheckStatus( shader );
glAttachShader( program, shader );
glDeleteShader( shader );
}
GLuint LoadProgram( const char* vert, const char* geom, const char* frag )
{
GLuint prog = glCreateProgram();
if( vert ) AttachShader( prog, GL_VERTEX_SHADER, vert );
if( geom ) AttachShader( prog, GL_GEOMETRY_SHADER, geom );
if( frag ) AttachShader( prog, GL_FRAGMENT_SHADER, frag );
glLinkProgram( prog );
CheckStatus( prog );
return prog;
}
#define GLSL(version, shader) "#version " #version "\n" #shader
const char* vert = GLSL
(
120,
uniform mat4 u_projection;
uniform mat4 u_modelview;
attribute vec3 a_pos;
attribute vec3 a_bc;
varying vec3 v_bc;
void main()
{
v_bc = a_bc;
gl_Position = u_projection * u_modelview * vec4( a_pos, 1.0 );
}
);
const char* frag = GLSL
(
120,
varying vec3 v_bc;
void main()
{
gl_FragColor = vec4( v_bc, 1.0 );
}
);
struct Vertex
{
Vertex( const vec3& pos, const vec3& bc )
: pos( pos )
, bc( bc )
{}
vec3 pos;
vec3 bc;
};
void AddTriangle( const vec3& p1, const vec3& p2, const vec3& p3, vector< Vertex >& verts )
{
verts.push_back( Vertex( p1, vec3( 1, 0, 0 ) ) );
verts.push_back( Vertex( p2, vec3( 0, 1, 0 ) ) );
verts.push_back( Vertex( p3, vec3( 0, 0, 1 ) ) );
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
double w = glutGet( GLUT_WINDOW_WIDTH );
double h = glutGet( GLUT_WINDOW_HEIGHT );
double ar = w / h;
mat4 projection = glm::ortho< float >( -2 * ar, 2 * ar, -2.0, 2.0, -1.0, 1.0 );
mat4 modelview = mat4( 1.0 );
// prepare to render
static GLuint prog = LoadProgram( vert, NULL, frag );
glUseProgram( prog );
GLint proj = glGetUniformLocation( prog, "u_projection" );
glUniformMatrix4fv( proj, 1, GL_FALSE, glm::value_ptr( projection ) );
GLint model = glGetUniformLocation( prog, "u_modelview" );
glUniformMatrix4fv( model, 1, GL_FALSE, glm::value_ptr( modelview) );
vector< Vertex > verts;
AddTriangle
(
vec3( 0, 0, 0 ),
vec3( 1, 0, 0 ),
vec3( 1, 1, 0 ),
verts
);
GLint pos = glGetAttribLocation( prog, "a_pos" );
glVertexAttribPointer( pos, 3, GL_FLOAT, GL_FALSE, sizeof( Vertex ), &verts[0].pos );
glEnableVertexAttribArray( pos );
GLint bc = glGetAttribLocation( prog, "a_bc" );
glVertexAttribPointer( bc, 3, GL_FLOAT, GL_FALSE, sizeof( Vertex ), &verts[0].bc );
glEnableVertexAttribArray( bc );
glDrawArrays( GL_TRIANGLES, 0, verts.size() );
glutSwapBuffers();
}
int main(int argc, char **argv)
{
glutInit( &argc, argv );
glutSetOption( GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_GLUTMAINLOOP_RETURNS );
glutInitDisplayMode( GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE );
glutInitWindowSize( 600, 600 );
glutCreateWindow( "GLUT" );
glewInit();
glutDisplayFunc( display );
glutMainLoop();
return 0;
}
如果v_bc == (1,0,0)
,则您的片段位于第一个顶点。
如果v_bc == (0,1,0)
,则您的片段位于第二个顶点。
如果v_bc == (0,0,1)
,则您的片段位于第三个顶点。
答案 2 :(得分:0)
感谢您的支持和想法,我需要的是通过顶点着色器将顶点的LOCAL位置传递给片段着色器。我们可以在没有任何额外计算的情况下完成它,因为它是顶点着色器已知的值。我仍然没有在开始时我想要的东西,但现在我知道如何使用片段着色器来做我想要的效果:)。