gpt4 book ai didi

ios - Metal 同时有纹理和无纹理,多重混合

转载 作者:搜寻专家 更新时间:2023-10-31 22:58:36 24 4
gpt4 key购买 nike

我在 Metal 中绘制了 2 个不同的顶点缓冲区,一个带有纹理(忽略顶点颜色数据),另一个没有纹理(仅绘制顶点颜色数据):

let commandBuffer = self.commandQueue.makeCommandBuffer()
let commandEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: rpd)

//render first buffer with texture
commandEncoder.setRenderPipelineState(self.rps)
commandEncoder.setVertexBuffer(self.vertexBuffer1, offset: 0, at: 0)
commandEncoder.setVertexBuffer(self.uniformBuffer, offset: 0, at: 1)
commandEncoder.setFragmentTexture(self.texture, at: 0)
commandEncoder.setFragmentSamplerState(self.samplerState, at: 0)
commandEncoder.drawPrimitives(type: .triangle, vertexStart: 0, vertexCount: count1, instanceCount: 1)


//render second buffer without texture
commandEncoder.setRenderPipelineState(self.rps)
commandEncoder.setVertexBuffer(self.vertexBuffer2, offset: 0, at: 0)
commandEncoder.setVertexBuffer(self.uniformBuffer, offset: 0, at: 1)
commandEncoder.setFragmentTexture(nil, at: 0)
commandEncoder.drawPrimitives(type: .triangle, vertexStart: 0, vertexCount: count2, instanceCount: 1)

commandEncoder.endEncoding()
commandBuffer.present(drawable)
commandBuffer.commit()

着色器看起来像这样:

#include <metal_stdlib>
using namespace metal;

struct Vertex {
float4 position [[position]];
float4 color;
float4 texCoord;
};

struct Uniforms {
float4x4 modelMatrix;
};

vertex Vertex vertex_func(constant Vertex *vertices [[buffer(0)]],
constant Uniforms &uniforms [[buffer(1)]],
uint vid [[vertex_id]])
{
float4x4 matrix = uniforms.modelMatrix;
Vertex in = vertices[vid];
Vertex out;
out.position = matrix * float4(in.position);
out.color = in.color;
out.texCoord = in.texCoord;
return out;
}

fragment float4 fragment_func(Vertex vert [[stage_in]],
texture2d<float> tex2D [[ texture(0) ]],
sampler sampler2D [[ sampler(0) ]]) {

if (vert.color[0] == 0 && vert.color[1] == 0 && vert.color[2] == 0) {
//texture color
return tex2D.sample(sampler2D, float2(vert.texCoord[0],vert.texCoord[1]));
}
else {
//color color
return vert.color;
}

}

有更好的方法吗?我想使用我设置为黑色的纹理的任何顶点,着色器检查颜色是否为黑色,如果是则使用纹理,否则使用颜色。

此外,如果彩色多边形和纹理多边形在屏幕上重叠,是否可以使用乘法函数将它们混合在一起? MTLBlendOperation 似乎只有加/减/最小/最大选项,没有乘法?

最佳答案

另一种方法是使用两个不同的片段函数,一个渲染带纹理的片段,另一个处理彩色顶点。

首先,您需要在加载时创建两个不同的MTLRenderPipelineState:

let desc = MTLRenderPipelineDescriptor()    

/* ...load all other settings in the descriptor... */

// Load the common vertex function.
desc.vertexFunction = library.makeFunction(name: "vertex_func")

// First create the one associated to the textured fragment function.
desc.fragmentFunction = library.makeFunction(name: "fragment_func_textured")
let texturedRPS = try! device.makeRenderPipelineState(descriptor: desc)

// Then modify the descriptor to create the state associated with the untextured fragment function.
desc.fragmentFunction = library.makeFunction(name: "fragment_func_untextured")
let untexturedRPS = try! device.makeRenderPipelineState(descriptor: desc)

然后在渲染时,在编码纹理对象的绘制命令之前设置纹理状态,在编码无纹理对象的绘制命令之前切换到无纹理对象。像这样:

//render first buffer with texture
commandEncoder.setRenderPipelineState(texturedRPS) // Set the textured state
commandEncoder.setVertexBuffer(self.vertexBuffer1, offset: 0, at: 0)
commandEncoder.setVertexBuffer(self.uniformBuffer, offset: 0, at: 1)
commandEncoder.setFragmentTexture(self.texture, at: 0)
commandEncoder.setFragmentSamplerState(self.samplerState, at: 0)
commandEncoder.drawPrimitives(type: .triangle, vertexStart: 0, vertexCount: count1, instanceCount: 1)

//render second buffer without texture
commandEncoder.setRenderPipelineState(untexturedRPS) // Set the untextured state
commandEncoder.setVertexBuffer(self.vertexBuffer2, offset: 0, at: 0)
commandEncoder.setVertexBuffer(self.uniformBuffer, offset: 0, at: 1)
// No need to set the fragment texture as we don't need it in the fragment function.
// commandEncoder.setFragmentTexture(nil, at: 0)
commandEncoder.drawPrimitives(type: .triangle, vertexStart: 0, vertexCount: count2, instanceCount: 1)

顶点函数不需要改变。虽然您需要将片段函数拆分为两个:

fragment float4 fragment_func_textured(Vertex vert [[stage_in]],
texture2d<float> tex2D [[ texture(0) ]],
sampler sampler2D [[ sampler(0) ]]) {
//texture color
return tex2D.sample(sampler2D, float2(vert.texCoord[0],vert.texCoord[1]));
}

fragment float4 fragment_func_untextured(Vertex vert [[stage_in]]) {
//color color
return vert.color;
}

您甚至可以继续使用两个不同的顶点函数来输出两个不同的顶点结构以节省几个字节。事实上,纹理片段函数只需要 texCoord 字段而不需要 color,而非纹理函数则相反。

编辑:您可以使用此片段函数同时使用纹理颜色和顶点颜色:

fragment float4 fragment_func_blended(Vertex vert [[stage_in]],
texture2d<float> tex2D [[ texture(0) ]],
sampler sampler2D [[ sampler(0) ]]) {
// texture color
float4 texture_sample = tex2D.sample(sampler2D, float2(vert.texCoord[0],vert.texCoord[1]));
// vertex color
float4 vertex_sample = vert.color;
// Blend the two together
float4 blended = texture_sample * vertex_sample;

// Or use another blending operation.
// float4 blended = mix(texture_sample, vertex_sample, mix_factor);
// Where mix_factor is in the range 0.0 to 1.0.
return blended;

}

关于ios - Metal 同时有纹理和无纹理,多重混合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40746930/

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