关于与金属混合
About blending with Metal
在WebGL (OpenGL)中,写在下面
gl.blendFuncSeparate (gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE);
在Swift金属
descriptor.colorAttachments [0] .isBlendingEnabled = true
descriptor.colorAttachments [0] .rgbBlendOperation = .add
descriptor.colorAttachments [0] .alphaBlendOperation = .add
descriptor.colorAttachments [0] .sourceRGBBlendFactor = .sourceAlpha
descriptor.colorAttachments [0] .sourceAlphaBlendFactor = .oneMinusSourceAlpha
descriptor.colorAttachments [0] .destinationRGBBlendFactor = .one
descriptor.colorAttachments [0] .destinationAlphaBlendFactor = .one
是正确答案吗?
P.S。
我问上面的问题是因为我想将下面的 WebGL 代码修复到 Metal。在WebGL中,混合体现在整体上,而在Metal中,是以描述符为单位进行的,所以我认为两者都是必要的。
function setupRendering(){
gl.viewport(0, 0, width, height);
gl.enable(gl.BLEND);
// alpha blending
gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE);
// blackclear
gl.clearColor(0.0, 0.0, 0.0, 0.0);
gl.bindFramebuffer(gl.FRAMEBUFFER, buffers.framebuffer);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
}
function renderMesh() {
gl.viewport(0, 0, width, height);
gl.bindFramebuffer(gl.FRAMEBUFFER, buffers[0].framebuffer);
gl.useProgram(firstProgram);
webgl.enableAttribute(planeVBO, attLocation, attStride);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, planeIBO);
gl.uniform2fv(resolution, [width, height]);
gl.drawElements(gl.TRIANGLES, plane.index.length, gl.UNSIGNED_SHORT, 0);
//
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
gl.clearColor(1.0, 1.0, 1.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.useProgram(renderingProgram);
webgl.enableAttribute(planeVBO, attLocation, attStride);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, planeIBO);
//
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, buffers[0].texture);
gl.uniform1i(renderingUniLocation.textureUnit, 0);
gl.drawElements(gl.TRIANGLES, plane.index.length, gl.UNSIGNED_SHORT, 0);
}
最终输出图像
在第一个可绘制对象上禁用帧混合:
let defaultLibrary = mtlDevice.makeDefaultLibrary()
let vertexFunction = defaultLibrary?.makeFunction(name: "textureVertexShader")
let fragmentFunction = defaultLibrary?.makeFunction(name: "textureFragmentShader")
let pipelineDescriptor = MTLRenderPipelineDescriptor()
pipelineDescriptor.label = "Drawable Render Pipeline"
pipelineDescriptor.sampleCount = mtkview.sampleCount
pipelineDescriptor.vertexFunction = vertexFunction
pipelineDescriptor.fragmentFunction = fragmentFunction
pipelineDescriptor.colorAttachments[0].pixelFormat = mtkview.colorPixelFormat
// alpha blending
//pipelineDescriptor.colorAttachments[0].isBlendingEnabled = true
//pipelineDescriptor.colorAttachments[0].rgbBlendOperation = .add
//pipelineDescriptor.colorAttachments[0].alphaBlendOperation = .add
//
//pipelineDescriptor.colorAttachments[0].sourceRGBBlendFactor = .sourceAlpha
//pipelineDescriptor.colorAttachments[0].sourceAlphaBlendFactor = .oneMinusSourceAlpha
//pipelineDescriptor.colorAttachments[0].destinationRGBBlendFactor = .one
//pipelineDescriptor.colorAttachments[0].destinationAlphaBlendFactor = .one
我得到了预期的结果:
更新:
我还将可绘制对象的颜色从黑色更改为白色:
fragment float4 simpleFragmentShader(VertexOut vertexIn [[stage_in]],
constant float2 &resolution [[buffer(0)]]) {
float2 resolution0 = float2(resolution[0], resolution[1]);
float2 p = (vertexIn.pos.xy) / min(resolution0.x, resolution0.y);
float cA = smoothstep(0.5, 0.51, length(p));
float3 colorB = float3(1.0, 1.0, 1.0);
return float4(colorB, cA);
}
在WebGL (OpenGL)中,写在下面
gl.blendFuncSeparate (gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE);
在Swift金属
descriptor.colorAttachments [0] .isBlendingEnabled = true
descriptor.colorAttachments [0] .rgbBlendOperation = .add
descriptor.colorAttachments [0] .alphaBlendOperation = .add
descriptor.colorAttachments [0] .sourceRGBBlendFactor = .sourceAlpha
descriptor.colorAttachments [0] .sourceAlphaBlendFactor = .oneMinusSourceAlpha
descriptor.colorAttachments [0] .destinationRGBBlendFactor = .one
descriptor.colorAttachments [0] .destinationAlphaBlendFactor = .one
是正确答案吗?
P.S。 我问上面的问题是因为我想将下面的 WebGL 代码修复到 Metal。在WebGL中,混合体现在整体上,而在Metal中,是以描述符为单位进行的,所以我认为两者都是必要的。
function setupRendering(){
gl.viewport(0, 0, width, height);
gl.enable(gl.BLEND);
// alpha blending
gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE);
// blackclear
gl.clearColor(0.0, 0.0, 0.0, 0.0);
gl.bindFramebuffer(gl.FRAMEBUFFER, buffers.framebuffer);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
}
function renderMesh() {
gl.viewport(0, 0, width, height);
gl.bindFramebuffer(gl.FRAMEBUFFER, buffers[0].framebuffer);
gl.useProgram(firstProgram);
webgl.enableAttribute(planeVBO, attLocation, attStride);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, planeIBO);
gl.uniform2fv(resolution, [width, height]);
gl.drawElements(gl.TRIANGLES, plane.index.length, gl.UNSIGNED_SHORT, 0);
//
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
gl.clearColor(1.0, 1.0, 1.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.useProgram(renderingProgram);
webgl.enableAttribute(planeVBO, attLocation, attStride);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, planeIBO);
//
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, buffers[0].texture);
gl.uniform1i(renderingUniLocation.textureUnit, 0);
gl.drawElements(gl.TRIANGLES, plane.index.length, gl.UNSIGNED_SHORT, 0);
}
最终输出图像
在第一个可绘制对象上禁用帧混合:
let defaultLibrary = mtlDevice.makeDefaultLibrary()
let vertexFunction = defaultLibrary?.makeFunction(name: "textureVertexShader")
let fragmentFunction = defaultLibrary?.makeFunction(name: "textureFragmentShader")
let pipelineDescriptor = MTLRenderPipelineDescriptor()
pipelineDescriptor.label = "Drawable Render Pipeline"
pipelineDescriptor.sampleCount = mtkview.sampleCount
pipelineDescriptor.vertexFunction = vertexFunction
pipelineDescriptor.fragmentFunction = fragmentFunction
pipelineDescriptor.colorAttachments[0].pixelFormat = mtkview.colorPixelFormat
// alpha blending
//pipelineDescriptor.colorAttachments[0].isBlendingEnabled = true
//pipelineDescriptor.colorAttachments[0].rgbBlendOperation = .add
//pipelineDescriptor.colorAttachments[0].alphaBlendOperation = .add
//
//pipelineDescriptor.colorAttachments[0].sourceRGBBlendFactor = .sourceAlpha
//pipelineDescriptor.colorAttachments[0].sourceAlphaBlendFactor = .oneMinusSourceAlpha
//pipelineDescriptor.colorAttachments[0].destinationRGBBlendFactor = .one
//pipelineDescriptor.colorAttachments[0].destinationAlphaBlendFactor = .one
我得到了预期的结果:
更新:
我还将可绘制对象的颜色从黑色更改为白色:
fragment float4 simpleFragmentShader(VertexOut vertexIn [[stage_in]],
constant float2 &resolution [[buffer(0)]]) {
float2 resolution0 = float2(resolution[0], resolution[1]);
float2 p = (vertexIn.pos.xy) / min(resolution0.x, resolution0.y);
float cA = smoothstep(0.5, 0.51, length(p));
float3 colorB = float3(1.0, 1.0, 1.0);
return float4(colorB, cA);
}