无法获取要在 GLSL Xamarin OpenGLView 控件中呈现的颜色
Cannot get colors to render in GLSL Xamarin OpenGLView contol
谁能帮忙解决以下问题?
使用 Visual Studio 2019 Xamarin Forms 项目我试图在 Android 模拟器中显示一个旋转的红色方块。我可以正常工作,但我的方块是黑色的:
这是我的 MainPage.xaml.cs 的代码(我使用 ES20,因为 ES10 没有我需要的 OpenGL 函数):
using OpenTK.Graphics.ES20;
using System;
using Xamarin.Forms;
namespace OGLMobile
{
public partial class MainPage : ContentPage
{
private float red = 1.0f;
private float green = 0.0f;
private float blue = 0.0f;
private const float halfWidth = 0.2f;
private float[] m_vertex_buffer_data = { 0.5f - halfWidth, 0.5f - halfWidth, 0.0f,
0.5f + halfWidth, 0.5f - halfWidth, 0.0f,
0.5f + halfWidth, 0.5f + halfWidth, 0.0f,
0.5f - halfWidth, 0.5f + halfWidth, 0.0f };
private string[] m_szVertexShader = null;
private string[] m_szFragmentShader = null;
private int m_nProgram = -1;
private int m_nVertexShaderHandle = -1;
private int m_nFragmentShaderHandle = -1;
private uint[] indices = { 0, 1, 2, 0, 2, 3 };
private int m_nVertexBuffer = -1;
bool m_bOGLParametersSet = false;
private void RotateSquare(float radians, float xRotationCentre, float yRotationCentre)
{
int[] nBaseIndices = { 0, 3, 6, 9 };
for (int nVertex = 0; nVertex <= 3 ; nVertex++)
{
int nIndex1 = nBaseIndices[nVertex];
int nIndex2 = nIndex1 + 1;
float offsetX = m_vertex_buffer_data[nIndex1] - xRotationCentre;
float offsetY = m_vertex_buffer_data[nIndex2] - yRotationCentre;
double xRotated = offsetX * Math.Cos(radians) - offsetY * Math.Sin(radians);
double yRotated = offsetX * Math.Sin(radians) + offsetY * Math.Cos(radians);
m_vertex_buffer_data[nIndex1] = (float)xRotated + xRotationCentre;
m_vertex_buffer_data[nIndex2] = (float)yRotated + yRotationCentre;
}
GL.BindBuffer(BufferTarget.ArrayBuffer, m_nVertexBuffer);
GL.BufferSubData(BufferTarget.ArrayBuffer, IntPtr.Zero, new IntPtr(m_vertex_buffer_data.Length * sizeof(float)), m_vertex_buffer_data);
}
public MainPage()
{
Title = "OpenGL";
var view = new OpenGLView { HasRenderLoop = true };
var toggle = new Switch { IsToggled = true };
m_szVertexShader = new string[1];
m_szFragmentShader = new string[1];
view.HeightRequest = 300;
view.WidthRequest = 300;
GL.Viewport(0, 0, 300, 300);
view.OnDisplay = r =>
{
if(!m_bOGLParametersSet) // Do this only on first rendering
{
CreateShader();
m_bOGLParametersSet = true;
GL.UseProgram(m_nProgram);
GL.GenBuffers(1, out m_nVertexBuffer);
GL.BindBuffer(BufferTarget.ArrayBuffer, m_nVertexBuffer);
GL.BufferData(BufferTarget.ArrayBuffer, new IntPtr(m_vertex_buffer_data.Length * sizeof(float)), m_vertex_buffer_data, BufferUsage.StaticDraw);
}
GL.ClearColor(0.0f, 0.0f, 1.0f, 1.0f);
GL.Clear((ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit));
RotateSquare(0.0174533f, 0.5f, 0.5f);
GL.EnableVertexAttribArray(0);
GL.BindBuffer(BufferTarget.ArrayBuffer, m_nVertexBuffer);
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 0, 0);
GL.DrawElements(BeginMode.Triangles, indices.Length, DrawElementsType.UnsignedInt, indices);
GL.DisableVertexAttribArray(0);
};
toggle.Toggled += (s, a) =>
{
view.HasRenderLoop = toggle.IsToggled;
};
var stack = new StackLayout
{
Padding = new Size(20, 20),
Children = { view, toggle}
};
Content = stack;
}
private void SetShaderSource()
{
m_szVertexShader[0] = "void main()" +
"{" +
"gl_Position = ftransform();" +
"}";
m_szFragmentShader[0] = "void main()" +
"{" +
"gl_FragColor = vec4(1.0,0.0,0.0,1.0);" +
"}";
}
private void CreateShader()
{
SetShaderSource();
int nVertexShaderSourceLength = m_szVertexShader[0].Length;
int nFragmentShaderLength = m_szFragmentShader[0].Length;
m_nVertexShaderHandle = GL.CreateShader(ShaderType.VertexShader);
m_nFragmentShaderHandle = GL.CreateShader(ShaderType.FragmentShader);
GL.ShaderSource(m_nVertexShaderHandle, 1, m_szVertexShader, new int[] { nVertexShaderSourceLength });
GL.ShaderSource(m_nFragmentShaderHandle, 1, m_szFragmentShader, new int[] { nVertexShaderSourceLength });
GL.CompileShader(m_nVertexShaderHandle);
GL.CompileShader(m_nFragmentShaderHandle);
string szVertexShaderLog = GL.GetShaderInfoLog(m_nVertexShaderHandle);
string szFragmentShaderLog = GL.GetShaderInfoLog(m_nFragmentShaderHandle);
m_nProgram = GL.CreateProgram();
GL.AttachShader(m_nProgram, m_nVertexShaderHandle);
GL.AttachShader(m_nProgram, m_nFragmentShaderHandle);
GL.LinkProgram(m_nProgram);
}
}
}
我的着色器一定是不正确的,如果我用垃圾字符串替换它们,我会得到相同的输出,所以系统一定是默认的东西。
我在调用 GetShaderInfoLog 时确实有编译错误,但我的着色器太简单了,我看不出问题所在:
非常感谢您的帮助,(现在已经坚持了一段时间。之前已经在桌面和 WebGL 上完成了大量的 OpenGL,但在移动设备上还没有任何运气)。
补充:非常感谢您的回复。我已经用兼容的着色器替换了着色器,不幸的是我仍然有一个黑色方块:
(图中写的是mediump,highp和lowp我也试过,结果一样)
我现在在编译顶点着色器时遇到一个不同的错误,而在片段着色器上没有错误 - 尽管我对后者有一个警告:
感谢您提供任何进一步的建议。
这些着色器不符合任何 GLSL ES 规范。参见 OpenGL ES Shading Language 1.00 Specification respectively. OpenGL ES Shading Language 3.00 Specification。
查看带有顶点着色器的工作着色器:
attribute vec3 a_position;
void main()
{
gl_Position = vec4(a_position, 1.0);
}
和片段着色器
precision mediump float;
void main()
{
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
我建议验证着色器编译是否有错误:
GL.CompileShader(m_nVertexShaderHandle);
string infoLogFrag = GL.GetShaderInfoLog(m_nVertexShaderHandle);
if (infoLogFrag != System.String.Empty)
{
System.Console.WriteLine(infoLogFrag);
}
GL.CompileShader(m_nFragmentShaderHandle);
string infoLogVert = GL.GetShaderInfoLog(m_nFragmentShaderHandle);
if (infoLogVert != System.String.Empty)
{
System.Console.WriteLine(infoLogVert);
}
并且程序链接没有错误:
GL.LinkProgram(m_nProgram);
string infoLogProg = GL.GetProgramInfoLog(m_nProgram );
if (infoLogProg != System.String.Empty)
{
System.Console.WriteLine(infoLogProg);
}
谁能帮忙解决以下问题?
使用 Visual Studio 2019 Xamarin Forms 项目我试图在 Android 模拟器中显示一个旋转的红色方块。我可以正常工作,但我的方块是黑色的:
这是我的 MainPage.xaml.cs 的代码(我使用 ES20,因为 ES10 没有我需要的 OpenGL 函数):
using OpenTK.Graphics.ES20;
using System;
using Xamarin.Forms;
namespace OGLMobile
{
public partial class MainPage : ContentPage
{
private float red = 1.0f;
private float green = 0.0f;
private float blue = 0.0f;
private const float halfWidth = 0.2f;
private float[] m_vertex_buffer_data = { 0.5f - halfWidth, 0.5f - halfWidth, 0.0f,
0.5f + halfWidth, 0.5f - halfWidth, 0.0f,
0.5f + halfWidth, 0.5f + halfWidth, 0.0f,
0.5f - halfWidth, 0.5f + halfWidth, 0.0f };
private string[] m_szVertexShader = null;
private string[] m_szFragmentShader = null;
private int m_nProgram = -1;
private int m_nVertexShaderHandle = -1;
private int m_nFragmentShaderHandle = -1;
private uint[] indices = { 0, 1, 2, 0, 2, 3 };
private int m_nVertexBuffer = -1;
bool m_bOGLParametersSet = false;
private void RotateSquare(float radians, float xRotationCentre, float yRotationCentre)
{
int[] nBaseIndices = { 0, 3, 6, 9 };
for (int nVertex = 0; nVertex <= 3 ; nVertex++)
{
int nIndex1 = nBaseIndices[nVertex];
int nIndex2 = nIndex1 + 1;
float offsetX = m_vertex_buffer_data[nIndex1] - xRotationCentre;
float offsetY = m_vertex_buffer_data[nIndex2] - yRotationCentre;
double xRotated = offsetX * Math.Cos(radians) - offsetY * Math.Sin(radians);
double yRotated = offsetX * Math.Sin(radians) + offsetY * Math.Cos(radians);
m_vertex_buffer_data[nIndex1] = (float)xRotated + xRotationCentre;
m_vertex_buffer_data[nIndex2] = (float)yRotated + yRotationCentre;
}
GL.BindBuffer(BufferTarget.ArrayBuffer, m_nVertexBuffer);
GL.BufferSubData(BufferTarget.ArrayBuffer, IntPtr.Zero, new IntPtr(m_vertex_buffer_data.Length * sizeof(float)), m_vertex_buffer_data);
}
public MainPage()
{
Title = "OpenGL";
var view = new OpenGLView { HasRenderLoop = true };
var toggle = new Switch { IsToggled = true };
m_szVertexShader = new string[1];
m_szFragmentShader = new string[1];
view.HeightRequest = 300;
view.WidthRequest = 300;
GL.Viewport(0, 0, 300, 300);
view.OnDisplay = r =>
{
if(!m_bOGLParametersSet) // Do this only on first rendering
{
CreateShader();
m_bOGLParametersSet = true;
GL.UseProgram(m_nProgram);
GL.GenBuffers(1, out m_nVertexBuffer);
GL.BindBuffer(BufferTarget.ArrayBuffer, m_nVertexBuffer);
GL.BufferData(BufferTarget.ArrayBuffer, new IntPtr(m_vertex_buffer_data.Length * sizeof(float)), m_vertex_buffer_data, BufferUsage.StaticDraw);
}
GL.ClearColor(0.0f, 0.0f, 1.0f, 1.0f);
GL.Clear((ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit));
RotateSquare(0.0174533f, 0.5f, 0.5f);
GL.EnableVertexAttribArray(0);
GL.BindBuffer(BufferTarget.ArrayBuffer, m_nVertexBuffer);
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 0, 0);
GL.DrawElements(BeginMode.Triangles, indices.Length, DrawElementsType.UnsignedInt, indices);
GL.DisableVertexAttribArray(0);
};
toggle.Toggled += (s, a) =>
{
view.HasRenderLoop = toggle.IsToggled;
};
var stack = new StackLayout
{
Padding = new Size(20, 20),
Children = { view, toggle}
};
Content = stack;
}
private void SetShaderSource()
{
m_szVertexShader[0] = "void main()" +
"{" +
"gl_Position = ftransform();" +
"}";
m_szFragmentShader[0] = "void main()" +
"{" +
"gl_FragColor = vec4(1.0,0.0,0.0,1.0);" +
"}";
}
private void CreateShader()
{
SetShaderSource();
int nVertexShaderSourceLength = m_szVertexShader[0].Length;
int nFragmentShaderLength = m_szFragmentShader[0].Length;
m_nVertexShaderHandle = GL.CreateShader(ShaderType.VertexShader);
m_nFragmentShaderHandle = GL.CreateShader(ShaderType.FragmentShader);
GL.ShaderSource(m_nVertexShaderHandle, 1, m_szVertexShader, new int[] { nVertexShaderSourceLength });
GL.ShaderSource(m_nFragmentShaderHandle, 1, m_szFragmentShader, new int[] { nVertexShaderSourceLength });
GL.CompileShader(m_nVertexShaderHandle);
GL.CompileShader(m_nFragmentShaderHandle);
string szVertexShaderLog = GL.GetShaderInfoLog(m_nVertexShaderHandle);
string szFragmentShaderLog = GL.GetShaderInfoLog(m_nFragmentShaderHandle);
m_nProgram = GL.CreateProgram();
GL.AttachShader(m_nProgram, m_nVertexShaderHandle);
GL.AttachShader(m_nProgram, m_nFragmentShaderHandle);
GL.LinkProgram(m_nProgram);
}
}
}
我的着色器一定是不正确的,如果我用垃圾字符串替换它们,我会得到相同的输出,所以系统一定是默认的东西。
我在调用 GetShaderInfoLog 时确实有编译错误,但我的着色器太简单了,我看不出问题所在:
非常感谢您的帮助,(现在已经坚持了一段时间。之前已经在桌面和 WebGL 上完成了大量的 OpenGL,但在移动设备上还没有任何运气)。
补充:非常感谢您的回复。我已经用兼容的着色器替换了着色器,不幸的是我仍然有一个黑色方块:
(图中写的是mediump,highp和lowp我也试过,结果一样)
我现在在编译顶点着色器时遇到一个不同的错误,而在片段着色器上没有错误 - 尽管我对后者有一个警告:
感谢您提供任何进一步的建议。
这些着色器不符合任何 GLSL ES 规范。参见 OpenGL ES Shading Language 1.00 Specification respectively. OpenGL ES Shading Language 3.00 Specification。
查看带有顶点着色器的工作着色器:
attribute vec3 a_position;
void main()
{
gl_Position = vec4(a_position, 1.0);
}
和片段着色器
precision mediump float;
void main()
{
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
我建议验证着色器编译是否有错误:
GL.CompileShader(m_nVertexShaderHandle);
string infoLogFrag = GL.GetShaderInfoLog(m_nVertexShaderHandle);
if (infoLogFrag != System.String.Empty)
{
System.Console.WriteLine(infoLogFrag);
}
GL.CompileShader(m_nFragmentShaderHandle);
string infoLogVert = GL.GetShaderInfoLog(m_nFragmentShaderHandle);
if (infoLogVert != System.String.Empty)
{
System.Console.WriteLine(infoLogVert);
}
并且程序链接没有错误:
GL.LinkProgram(m_nProgram);
string infoLogProg = GL.GetProgramInfoLog(m_nProgram );
if (infoLogProg != System.String.Empty)
{
System.Console.WriteLine(infoLogProg);
}