- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
经过几天的挣扎,我来到了这里。我正在尝试将自定义的每顶点 vec3 属性传递给基于 this 的自定义着色器教程。本教程描述了如何传递实际工作正常的自定义制服。然而,当我尝试修改代码以传递我的自定义逐顶点属性时,似乎没有任何内容被传输到顶点着色器,我不知道如何让它工作。
到目前为止,我已经完成了以下工作:
我用 modelBuilder.createBox() 创建了几个盒子(所以我确定每个模型都有 24 个顶点)
然后我生成了一个包含实际属性数据的 FloatBuffer,如下所示:
int[] data = new int[]{x1, y1, z1, x1, y1, z1, ...}
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(data.length * 4);
byteBuffer.order(ByteOrder.nativeOrder());
mAttributeBuffer = byteBuffer.asFloatBuffer();
mAttributeBuffer.put(data);
mAttributeBuffer.position(0);
然后我正在初始化相应的属性位置变量(成功,a_coord >= 0):
a_coord = program.getAttributeLocation("a_coord");
在那之后,在自定义着色器的 render(Renderable)
方法中的 libgdx 端,我将缓冲区传递给 OpenGL,如下所示:
program.setVertexAttribute(a_coord, 3, Gdx.gl20.GL_FLOAT, false, 0, mAttributeBuffer);
我的自定义顶点着色器如下:
attribute vec3 a_position;
attribute vec3 a_normal;
attribute vec2 a_texCoord0;
uniform mat4 u_worldTrans;
uniform mat4 u_projTrans;
varying vec2 v_texCoord0;
//my custom attribute
attribute vec2 a_coord;
void main() {
v_texCoord0 = a_texCoord0;
float posY = a_position.y + a_coord.y;
gl_Position = u_projTrans * u_worldTrans * vec4(a_position.x, posY, a_position.z, 1.0);
}
问题
目前每个顶点的 a_coord 都为 0。我缺少什么以及如何将自定义属性正确传递给顶点着色器?
我猜问题出在 VBO 字段的某处以及 libGDX 将属性数据传递给顶点的方式,但我仍然无法弄清楚如何让它工作。
如果有人能指出我在这个问题上的正确方向,我会很高兴。
完整代码:
主 AplicationListener 类:
public class ProtoGame implements ApplicationListener {
public ProtoGame()
{
super();
}
public PerspectiveCamera cam;
public CameraInputController camController;
public Model model;
public Array<ModelInstance> instances = new Array<ModelInstance>();
public ModelBatch modelBatch;
@Override
public void create () {
cam = new PerspectiveCamera(67, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
cam.position.set(0f, 8f, 8f);
cam.lookAt(0,0,0);
cam.near = 1f;
cam.far = 300f;
cam.update();
camController = new CameraInputController(cam);
Gdx.input.setInputProcessor(camController);
ModelBuilder modelBuilder = new ModelBuilder();
model = modelBuilder.createBox(1f, 1f, 1f,
new Material(),
VertexAttributes.Usage.Position | VertexAttributes.Usage.Normal | VertexAttributes.Usage.TextureCoordinates);
Color colorU = new Color(), colorV = new Color();
for (int x = -5; x <= 5; x+=2) {
for (int z = -5; z<=5; z+=2) {
ModelInstance instance = new ModelInstance(model, x, 0, z);
//this is where I'll put per-vertex attribute data for every instance
//but for now it's hardcoded in the Shader class so the data is the same across instances
TestShader.DoubleColorAttribute attr = new TestShader.DoubleColorAttribute(TestShader.DoubleColorAttribute.DiffuseUV,
colorU.set((x+5f)/10f, 1f - (z+5f)/10f, 0, 1),
colorV.set(1f - (x+5f)/10f, 0, (z+5f)/10f, 1));
instance.materials.get(0).set(attr);
instances.add(instance);
}
}
modelBatch = new ModelBatch(new BaseShaderProvider() {
@Override
protected Shader createShader(Renderable renderable) {
return new TestShader();
}
});
}
@Override
public void render () {
camController.update();
Gdx.gl.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
modelBatch.begin(cam);
for (ModelInstance instance : instances)
modelBatch.render(instance);
modelBatch.end();
}
@Override
public void dispose () {
model.dispose();
modelBatch.dispose();
}
}
自定义 libgdx 着色器类:
public class TestShader implements Shader {
private FloatBuffer mAttributeBuffer;
ShaderProgram program;
Camera camera;
RenderContext context;
int u_projTrans;
int u_worldTrans;
int u_colorU;
int u_colorV;
int a_coord;
private static String getCustomVertexShader() {
return Gdx.files.internal("shader/test.vertex.glsl").readString();
}
private static String getCustomFragmentShader() {
return Gdx.files.internal("shader/test.fragment.glsl").readString();
}
@Override
public void init() {
program = new ShaderProgram(getCustomVertexShader(), getCustomFragmentShader());
if (!program.isCompiled())
throw new GdxRuntimeException(program.getLog());
//tutorial's logic to init custom uniform locations
u_projTrans = program.getUniformLocation("u_projTrans");
u_worldTrans = program.getUniformLocation("u_worldTrans");
u_colorU = program.getUniformLocation("u_colorU");
u_colorV = program.getUniformLocation("u_colorV");
//initing custom attribute location
a_coord = program.getAttributeLocation("a_coord");
//generating data and passing it to nio Buffer
float data[] = generateData();
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(data.length * 4);
byteBuffer.order(ByteOrder.nativeOrder());
mAttributeBuffer = byteBuffer.asFloatBuffer();
mAttributeBuffer.put(data);
mAttributeBuffer.position(0);
}
private float[] generateData() {
Vector3[] dataArray = new Vector3[1];
dataArray[0] = new Vector3(2, 2, 2);
int components = 3;
int vertexPerModel = 24;
float[] data = new float[dataArray.length * components * vertexPerModel];
for(int i = 0; i < dataArray.length; ++i){
int i3 = i * components;
for(int j = 0; j < vertexPerModel; ++j) {
int j3 = j * components;
data[i3 + 0 + j3] = dataArray[i].x;
data[i3 + 1 + j3] = dataArray[i].y;
data[i3 + 2 + j3] = dataArray[i].z;
}
}
return data;
}
@Override
public void dispose() {
program.dispose();
}
@Override
public void begin(Camera camera, RenderContext context) {
this.camera = camera;
this.context = context;
program.begin();
program.setUniformMatrix(u_projTrans, camera.combined);
context.setDepthTest(GL20.GL_LEQUAL);
context.setCullFace(GL20.GL_BACK);
}
@Override
public void render(Renderable renderable) {
program.setUniformMatrix(u_worldTrans, renderable.worldTransform);
//tutorial's logic to pass uniform
DoubleColorAttribute attribute = ((DoubleColorAttribute) renderable.material.get(DoubleColorAttribute.DiffuseUV));
program.setUniformf(u_colorU, attribute.color1.r, attribute.color1.g, attribute.color1.b);
program.setUniformf(u_colorV, attribute.color2.r, attribute.color2.g, attribute.color2.b);
//passing my custom attributes to the vertex shader
program.setVertexAttribute(a_coord, 3, Gdx.gl20.GL_FLOAT, false, 0, mAttributeBuffer);
renderable.mesh.render(program, renderable.primitiveType,
renderable.meshPartOffset, renderable.meshPartSize);
}
@Override
public void end() {
program.end();
}
@Override
public int compareTo(Shader other) {
return 0;
}
@Override
public boolean canRender(Renderable renderable) {
return renderable.material.has(DoubleColorAttribute.DiffuseUV);
}
}
最佳答案
我终于能够将自定义属性传递给顶点着色器了!非常感谢@Xoppa 为我指明了正确的方向。
这是我目前得到的有效解决方案(我愿意接受任何关于如何以更优雅的方式实现它的进一步建议):
首先,正如 Xoppa 在评论中所述,它需要创建一个在构建模型时提供自定义顶点结构的模型。所以模型创建可能看起来像这样:
VertexAttribute posAttr = new VertexAttribute(VertexAttributes.Usage.Position, 3, ShaderProgram.POSITION_ATTRIBUTE);
...
VertexAttribute customVertexAttr = new VertexAttribute(512, 3, "a_custom");
VertexAttributes vertexAttributes = new VertexAttributes(
posAttr,
...
customVertexAttr);
ModelBuilder modelBuilder = new ModelBuilder();
modelBuilder.begin();
modelBuilder.
part("box", GL20.GL_TRIANGLES, vertexAttributes, new Material()).
box(1f, 1f, 1f);
model = modelBuilder.end();
或者与MeshBuilder
相同:
MeshBuilder meshBuilder = new MeshBuilder();
VertexAttributes vertexAttributes = new VertexAttributes(...);
meshBuilder.begin(vertexAttributes);
meshBuilder.part("box", GL20.GL_TRIANGLES);
meshBuilder.setColor(color);
meshBuilder.box(1f, 1f, 1f);
Mesh mesh = meshBuilder.end();
此代码将根据提供的属性创建带有包含附加数据的顶点的模型。是时候填充相应的顶点数组了。你需要一个网格 - 它存储顶点数组 - 一个接一个顶点接一个顶点的打包属性的平面数组。所以你需要的是每个顶点的一些属性以及需要修改的属性的偏移量。 Mesh 存储所有这些数据:
Mesh mesh = model.meshes.get(0);
int numVertices = mesh.getNumVertices();
// vertex size and offset are in byte so we need to divide it by 4
int vertexSize = mesh.getVertexAttributes().vertexSize / 4;
//it's possible to use usage int here passed previously to VertexAttribute constructor.
VertexAttribute customAttribute = mesh.getVertexAttribute(512)
int offset = customAttribute.offset / 4;
float[] vertices = new float[numVertices * vertexSize];
mesh.getVertices(vertices);
我们准备传递数据:
List<Vector3> customData ...
for(int i = 0; i < numVertices; ++i){
int index = i * vertexSize + offset;
vertices[index + 0] = customData.get(i).x;
vertices[index + 1] = customData.get(i).y;
vertices[index + 2] = customData.get(i).z;
}
并且不要忘记将更新后的顶点数组传递回网格:
mesh.updateVertices(0, vertices);
就是这样。
这里还有一个辅助方法的实现,它使用 Usage
标志和自定义属性来创建默认属性的混合:
private VertexAttributes createMixedVertexAttribute(int defaultAtributes, List<VertexAttribute> customAttributes){
VertexAttributes defaultAttributes = MeshBuilder.createAttributes(defaultAtributes);
List<VertexAttribute> attributeList = new ArrayList<VertexAttribute>();
for(VertexAttribute attribute: defaultAttributes){
attributeList.add(attribute);
}
attributeList.addAll(customAttributes);
VertexAttribute[] typeArray = new VertexAttribute[0];
VertexAttributes mixedVertexAttributes = new VertexAttributes(attributeList.toArray(typeArray));
return mixedVertexAttributes;
}
完整来源:
public class ProtoGame implements ApplicationListener {
private static final int CUSTOM_ATTRIBUTE_USAGE = 512;
public ProtoGame()
{
super();
}
public PerspectiveCamera cam;
public CameraInputController camController;
public Model model;
public Array<ModelInstance> instances = new Array<ModelInstance>();
public ModelBatch modelBatch;
@Override
public void create () {
cam = new PerspectiveCamera(67, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
cam.position.set(0f, 8f, 8f);
cam.lookAt(0, 0, 0);
cam.near = 1f;
cam.far = 300f;
cam.update();
camController = new CameraInputController(cam);
Gdx.input.setInputProcessor(camController);
Model model = createModelWithCustomAttributes();
Mesh mesh = model.meshes.get(0);
setCustomAttributeData(mesh);
Color colorU = new Color(), colorV = new Color();
for (int x = -5; x <= 5; x+=2) {
for (int z = -5; z<=5; z+=2) {
ModelInstance instance = new ModelInstance(model, x, 0, z);
TestShader.DoubleColorAttribute attr = new TestShader.DoubleColorAttribute(TestShader.DoubleColorAttribute.DiffuseUV,
colorU.set((x+5f)/10f, 1f - (z+5f)/10f, 0, 1),
colorV.set(1f - (x+5f)/10f, 0, (z+5f)/10f, 1));
instance.materials.get(0).set(attr);
instances.add(instance);
}
}
modelBatch = new ModelBatch(new BaseShaderProvider() {
@Override
protected Shader createShader(Renderable renderable) {
return new TestShader();
}
});
}
@Override
public void render () {
camController.update();
Gdx.gl.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
modelBatch.begin(cam);
for (ModelInstance instance : instances)
modelBatch.render(instance);
modelBatch.end();
}
private Model createModelWithCustomAttributes() {
int defaultAttributes = VertexAttributes.Usage.Position | VertexAttributes.Usage.Normal | VertexAttributes.Usage.TextureCoordinates;
VertexAttribute customVertexAttr = new VertexAttribute(CUSTOM_ATTRIBUTE_USAGE, 3, "a_custom");
List<VertexAttribute> customAttributeList = new ArrayList<VertexAttribute>();
customAttributeList.add(customVertexAttr);
VertexAttributes vertexAttributes = createMixedVertexAttribute(defaultAttributes, customAttributeList);
ModelBuilder modelBuilder = new ModelBuilder();
modelBuilder.begin();
modelBuilder.
part("box", GL20.GL_TRIANGLES, vertexAttributes, new Material()).
box(1f, 1f, 1f);
return modelBuilder.end();
}
private void setCustomAttributeData(Mesh mesh) {
int numVertices = mesh.getNumVertices();
int vertexSize = mesh.getVertexAttributes().vertexSize / 4;
int offset = mesh.getVertexAttribute(CUSTOM_ATTRIBUTE_USAGE).offset / 4;
float[] vertices = new float[numVertices * vertexSize];
mesh.getVertices(vertices);
for(int i = 0; i < numVertices; ++i){
int index = i * vertexSize + offset;
vertices[index + 0] = i;
vertices[index + 1] = i;
vertices[index + 2] = i;
}
mesh.updateVertices(0, vertices);
}
@Override
public void dispose () {
model.dispose();
modelBatch.dispose();
}
private VertexAttributes createMixedVertexAttribute(int defaultAtributes, List<VertexAttribute> customAttributes){
VertexAttributes defaultAttributes = MeshBuilder.createAttributes(defaultAtributes);
List<VertexAttribute> attributeList = new ArrayList<VertexAttribute>();
for(VertexAttribute attribute: defaultAttributes){
attributeList.add(attribute);
}
attributeList.addAll(customAttributes);
VertexAttribute[] typeArray = new VertexAttribute[0];
VertexAttributes mixedVertexAttributes = new VertexAttributes(attributeList.toArray(typeArray));
return mixedVertexAttributes;
}
@Override
public void resize(int width, int height) {
}
@Override
public void pause() {
}
@Override
public void resume() {
}
}
顶点着色器:
attribute vec3 a_position;
attribute vec3 a_normal;
attribute vec2 a_texCoord0;
uniform mat4 u_worldTrans;
uniform mat4 u_projTrans;
varying vec2 v_texCoord0;
attribute vec3 a_custom;
void main() {
v_texCoord0 = a_texCoord0;
float posX = a_position.x + a_custom.x;
float posY = a_position.y + a_custom.y;
float posZ = a_position.z + a_custom.z;
gl_Position = u_projTrans * u_worldTrans * vec4(posX, posY, posZ, 1.0);
}
片段着色器
#ifdef GL_ES
precision mediump float;
#endif
uniform vec3 u_colorU;
uniform vec3 u_colorV;
varying vec2 v_texCoord0;
void main() {
gl_FragColor = vec4(v_texCoord0.x * u_colorU + v_texCoord0.y * u_colorV, 1.0);
}
关于Libgdx 自定义着色器逐顶点属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32222957/
我之前让 dll 注入(inject)器变得简单,但我有 Windows 7,我用 C# 和 C++ 做了它,它工作得很好!但是现在当我在 Windows 8 中尝试相同的代码时,它似乎没有以正确的方
我正在尝试制作一个名为 core-splitter 的元素,该元素在 1.0 中已弃用,因为它在我们的项目中起着关键作用。 如果您不知道 core-splitter 的作用,我可以提供一个简短的描述。
我有几个不同的蜘蛛,想一次运行所有它们。基于 this和 this ,我可以在同一个进程中运行多个蜘蛛。但是,我不知道如何设计一个信号系统来在所有蜘蛛都完成后停止 react 器。 我试过了: cra
有没有办法在达到特定条件时停止扭曲 react 器。例如,如果一个变量被设置为某个值,那么 react 器应该停止吗? 最佳答案 理想情况下,您不会将变量设置为一个值并停止 react 器,而是调用
https://code.angularjs.org/1.0.0rc9/angular-1.0.0rc9.js 上面的链接定义了外部js文件,我不知道Angular-1.0.0rc9.js的注入(in
我正在尝试运行一个函数并将服务注入(inject)其中。我认为这可以使用 $injector 轻松完成.所以我尝试了以下(简化示例): angular.injector().invoke( [ "$q
在 google Guice 中,我可以使用函数 createInjector 创建基于多个模块的注入(inject)器。 因为我使用 GWT.create 在 GoogleGin 中实例化注入(in
我在 ASP.NET Core 1.1 解决方案中使用配置绑定(bind)。基本上,我在“ConfigureServices Startup”部分中有一些用于绑定(bind)的简单代码,如下所示: s
我在 Spring MVC 中设置 initBinder 时遇到一些问题。我有一个 ModelAttribute,它有一个有时会显示的字段。 public class Model { privat
我正在尝试通过jquery post发布knockoutjs View 模型 var $form = $('#barcodeTemplate form'); var data = ko.toJS(vm
如何为包含多态对象集合的复杂模型编写自定义模型绑定(bind)程序? 我有下一个模型结构: public class CustomAttributeValueViewModel { publi
您好,我正在尝试实现我在 this article 中找到的扩展方法对于简单的注入(inject)器,因为它不支持开箱即用的特定构造函数的注册。 根据这篇文章,我需要用一个假的委托(delegate)
你好,我想自动注册我的依赖项。 我现在拥有的是: public interface IRepository where T : class public interface IFolderReposi
我正在使用 Jasmine 测试一些 Angular.js 代码。为此,我需要一个 Angular 注入(inject)器: var injector = angular.injector(['ng'
我正在使用 Matlab 代码生成器。不可能包含代码风格指南。这就是为什么我正在寻找一个工具来“ reshape ”、重命名和重新格式化生成的代码,根据我的: 功能横幅约定 文件横幅约定 命名约定 等
这个问题在这里已经有了答案: Where and why do I have to put the "template" and "typename" keywords? (8 个答案) 关闭 8
我开发了一种工具,可以更改某些程序的外观。为此,我需要在某些进程中注入(inject)一个 dll。 现在我基本上使用这个 approach .问题通常是人们无法注入(inject) dll,因为他们
我想使用 swing、spring 和 hibernate 编写一个 java 应用程序。 我想使用数据绑定(bind)器用 bean 的值填充 gui,并且我还希望它反射(reflect) gui
我有这段代码,当两个蜘蛛完成后,程序仍在运行。 #!C:\Python27\python.exe from twisted.internet import reactor from scrapy.cr
要点是 Spring Batch (v2) 测试框架具有带有 @Autowired 注释的 JobLauncherTestUtils.setJob。我们的测试套件有多个 Job 类提供者。因为这个类不
我是一名优秀的程序员,十分优秀!