我正在用 C# 和 OpenTK 编写关卡编辑器,并想看看更复杂的着色器是否可以正常工作。所以我在这里抓住了这个我的工艺着色器https://www.shadertoy.com/view/MdlGz4。
但我无法让它工作,我不断收到这个错误:
Failed to link shader program!
Fragment info
-------------
Internal error: assembly compile error for fragment shader at offset 392911:
-- error message --
line 16405, column 1: error: too many instructions
-- internal assembly text --
!!NVfp5.0
OPTION NV_bindless_texture;
OPTION NV_shader_atomic_float;
# cgc version 3.1.0001, build date Feb 9 2013
# command line args:
#vendor NVIDIA Corporation
#version 3.1.0.1
#profile gp5fp
shadertoy 版本在我的浏览器中运行良好。所以我知道我的硬件(GTX 680)可以处理它。我在片段着色器中使用#version 400,希望更高版本允许更多指令。但这也无济于事。所以我的问题是,我如何加载/编译这么长的片段着色器?
这是我正在尝试运行的实际着色器:
顶点:
#version 400
uniform mat4 camera;
uniform mat4 model;
in vec3 in_vertex;
in vec4 in_color;
in vec2 in_uv;
out vec2 frag_TexCoord;
out vec4 frag_Color;
void main()
{
gl_Position = camera * model * vec4(in_vertex, 1);
frag_TexCoord = in_uv;
frag_Color = in_color;
}
分段:
#version 400
uniform vec2 iResolution;
uniform float iGlobalTime;
in vec4 frag_Color;
in vec2 frag_TexCoord;
out vec4 final_color;
// Created by Reinder Nijhoff 2013
//
// port of javascript minecraft: http://jsfiddle.net/uzMPU/
// original code by Markus Persson: https://twitter.com/notch/status/275331530040160256
float hash( float n ) {
return fract(sin(n)*43758.5453);
}
// port of minecraft
bool getMaterialColor( int i, vec2 coord, out vec3 color ) {
// 16x16 tex
vec2 uv = floor( coord );
float n = uv.x + uv.y*347.0 + 4321.0 * float(i);
float h = hash(n);
float br = 1. - h * (96./255.
);
color = vec3( 150./255., 108./255., 74./255.); // 0x966C4A;
if (i == 4) {
color = vec3( 127./255., 127./255., 127./255.); // 0x7F7F7F;
}
float xm1 = mod((uv.x * uv.x * 3. + uv.x * 81.) / 4., 4.);
if (i == 1) {
if( uv.y < (xm1 + 18.)) {
color = vec3( 106./255., 170./255., 64./255.); // 0x6AAA40;
} else if (uv.y < (xm1 + 19.)) {
br = br * (2. / 3.);
}
}
if (i == 7) {
color = vec3( 103./255., 82./255., 49./255.); // 0x675231;
if (uv.x > 0. && uv.x < 15.
&& ((uv.y > 0. && uv.y < 15.) || (uv.y > 32. && uv.y < 47.))) {
color = vec3( 188./255., 152./255., 98./255.); // 0xBC9862;
float xd = (uv.x - 7.);
float yd = (mod(uv.y, 16.) - 7.);
if (xd < 0.)
xd = 1. - xd;
if (yd < 0.)
yd = 1. - yd;
if (yd > xd)
xd = yd;
br = 1. - (h * (32./255.) + mod(xd, 4.) * (32./255.));
} else if ( h < 0.5 ) {
br = br * (1.5 - mod(uv.x, 2.));
}
}
if (i == 5) {
color = vec3( 181./255., 58./255., 21./255.); // 0xB53A15;
if ( mod(uv.x + (floor(uv.y / 4.) * 5.), 8.) == 0. || mod( uv.y, 4.) == 0.) {
color = vec3( 188./255., 175./255., 165./255.); // 0xBCAFA5;
}
}
if (i == 9) {
color = vec3( 64./255., 64./255., 255./255.); // 0x4040ff;
}
float brr = br;
if (uv.y >= 32.)
brr /= 2.;
if (i == 8) {
color = vec3( 80./255., 217./255., 55./255.); // 0x50D937;
if ( h < 0.5) {
return false;
}
}
color *= brr;
return true;
}
int getMap( vec3 pos ) {
vec3 posf = floor( (pos - vec3(32.)) );
float n = posf.x + posf.y*517.0 + 1313.0*posf.z;
float h = hash(n);
if( h > sqrt( sqrt( dot( posf.yz, posf.yz )*0.16 ) ) - 0.8 ) {
return 0;
}
return int( hash( n * 465.233 ) * 16. );
}
vec3 renderMinecraft( vec2 uv ) {
float xRot = sin( iGlobalTime*0.5 ) * 0.4 + (3.1415 / 2.);
float yRot = cos( iGlobalTime*0.5 ) * 0.4;
float yCos = cos(yRot);
float ySin = sin(yRot);
float xCos = cos(xRot);
float xSin = sin(xRot);
vec3 opos = vec3( 32.5 + iGlobalTime * 6.4, 32.5, 32.5 );
float gggxd = (uv.x - 0.5) * (iResolution.x / iResolution.y );
float ggyd = (1.-uv.y - 0.5);
float ggzd = 1.;
float gggzd = ggzd * yCos + ggyd * ySin;
vec3 _posd = vec3( gggxd * xCos + gggzd * xSin,
ggyd * yCos - ggzd * ySin,
gggzd * xCos - gggxd * xSin );
vec3 col = vec3( 0. );
float br = 1.;
vec3 bdist = vec3( 255. - 100., 255. - 0., 255. - 50. );
float ddist = 0.;
float closest = 32.;
for ( int d = 0; d < 3; d++) {
float dimLength = _posd[d];
float ll = abs( 1. / dimLength );
vec3 posd = _posd * ll;;
float initial = fract( opos[d] );
if (dimLength > 0.) initial = 1. - initial;
float dist = ll * initial;
vec3 pos = opos + posd * initial;
if (dimLength < 0.) {
pos[d] -= 1.;
}
for (int i=0; i<30; i++) {
if( dist > closest )continue;
//int tex = getMap( mod( pos, 64. ) );
int tex = getMap( pos );
if (tex > 0) {
vec2 texcoord;
texcoord.x = mod(((pos.x + pos.z) * 16.), 16.);
texcoord.y = mod((pos.y * 16.), 16.) + 16.;
if (d == 1) {
texcoord.x = mod(pos.x * 16., 16.);
texcoord.y = mod(pos.z * 16., 16.);
if (posd.y < 0.)
texcoord.y += 32.;
}
if ( getMaterialColor( tex, texcoord, col ) ) {
ddist = 1. - (dist / 32.);
br = bdist[d];
closest = dist;
}
}
pos += posd;
dist += ll;
}
}
return col * ddist * (br/255.);
}
void main()
{
vec2 uv = frag_TexCoord.xy / iResolution.xy;
final_color = vec4( renderMinecraft( uv ) ,1.0);
}
澄清错误发生在哪里: 编译顶点和片段着色器的前两个步骤工作正常。它是返回 0 的链接 (GL.GetProgram())。对 GL.GetProgramInfo 的调用返回上述错误并以汇编代码列出程序(# 19337 指令,8 个 R-regs)。所以它确实有这么多行。
_vertexShader = GL.CreateShader(ShaderType.VertexShader);
GL.ShaderSource(_vertexShader, vertexProgram);
GL.CompileShader(_vertexShader);
GL.GetShader(_vertexShader, ShaderParameter.CompileStatus, out result);
if (result == 0)
{
System.Diagnostics.Debug.WriteLine(GL.GetString(StringName.ShadingLanguageVersion));
System.Diagnostics.Debug.WriteLine(GL.GetShaderInfoLog(_vertexShader));
}
//Create Fragment Shader
_fragShader = GL.CreateShader(ShaderType.FragmentShader);
GL.ShaderSource(_fragShader, fragmentProgram);
GL.CompileShader(_fragShader);
GL.GetShader(_fragShader, ShaderParameter.CompileStatus, out result);
if (result == 0)
{
System.Diagnostics.Debug.WriteLine(GL.GetString(StringName.ShadingLanguageVersion));
System.Diagnostics.Debug.WriteLine(GL.GetShaderInfoLog(_fragShader));
}
//Link to program
_shader = GL.CreateProgram();
GL.AttachShader(_shader, _vertexShader);
GL.AttachShader(_shader, _fragShader);
GL.LinkProgram(_shader);
GL.GetProgram(_shader, ProgramParameter.LinkStatus, out result);
if (result == 0)
{
System.Diagnostics.Debug.WriteLine("Failed to link shader program!");
System.Diagnostics.Debug.WriteLine(GL.GetProgramInfoLog(_shader));
GL.DeleteProgram(_shader);
}