无论出于何种原因,我都遇到了金属中 alpha 混合的问题。我正在绘制 MTKView,对于我创建的每个管道,我执行以下操作:
descriptor.colorAttachments[0].blendingEnabled = YES;
descriptor.colorAttachments[0].rgbBlendOperation = MTLBlendOperationAdd;
descriptor.colorAttachments[0].alphaBlendOperation = MTLBlendOperationAdd;
descriptor.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorSourceAlpha;
descriptor.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorSourceAlpha;
descriptor.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOneMinusSourceAlpha;
descriptor.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorOneMinusSourceAlpha;
Run Code Online (Sandbox Code Playgroud)
但是,无论出于何种原因,这都不会导致 alpha 测试发生。您甚至可以检查帧调试器,您将看到 alpha 为 0 的顶点被绘制为黑色而不是透明。
我的一个想法是,某些几何体最终位于完全相同的 z 平面上,因此如果 alpha 混合在同一 z 平面上不起作用,则可能会导致问题。但我不认为那是一回事。
为什么 alpha 混合不起作用?
我希望像透明玻璃一样混合。这样想。
我对金属非常陌生,因此在从丑陋的OpenGL状态机调用过渡到现代图形框架时,请多多包涵。我真的想确保我了解所有事情如何一起工作。
我已经阅读了大多数Apple文档,但是在描述各个组件的功能方面它们比它们如何组合起来做得更好。
我试图从本质上理解我是否应该有多个renderPipelines和renderEncoders在我的情况下。
要在更高层次上描述我的管道,是这样的:
因此,从本质上讲,将存在以下顶点/片段着色器对
将有以下纹理组
最终我的困惑是:
.setRenderPipelineState覆盖前一个吗?.setFragmentTexture在创建编码器后立即保留所有呼叫,还是只需要在需要时立即设置这些呼叫。我想如果有人带我逐步了解我需要什么以及为什么需要它,它将对我有帮助。理解某些psuedocode级别的renderCommandEncoder命令可能看起来是很有用的。
我在CS(Java)入门课程中,老师不允许我们在Queue或Stack上使用.peek().
显然,在堆栈上这是一个相当容易的解决方法,因为我们可能拥有任意数量的临时内注.可以简单地将值弹出到变量上并将其重新打开.这可能是它在幕后实施的方式.
在队列中,这会使事情变得复杂一些,但仍然可以完成.但是我不确定java如何实现queue.peek所以我不能在这里找到替换.
最终我很想知道.为什么不鼓励窥视堆栈和队列是一种好习惯?
作为Swift编码器,我对事物c方面的明显碎片感到困惑。不知何故,有Objective-C,Objective-C ++,c和c ++,它们都具有.h,.hpp,.m,.cpp等文件扩展名,但是我找不到关于哪个扩展名指向哪种文件类型的详尽文档。 XCode(尽管我相当确定c ++应该是.hpp和.cpp)。
这种混乱使我陷入困境,在尝试向快速代码公开C ++类时,我对自己的工作一无所知。让我解释一下我的策略。
我有一个由我修改过的XCode自动生成的桥接文件
桥接头
//
// Use this file to import your target's public headers that you would like to expose to Swift.
//
#include <stdio.h>
#include <stdlib.h>
int* main1() {
int *num;
num = (int *)malloc(1000 * sizeof(int));
for (int i = 0; i < 10; i++) {
num[i] = i;
}
num[10] = 10;
free(num);
return num;
}
Run Code Online (Sandbox Code Playgroud)
如果我解释正确,那么XCode会将其视为Objective-C代码的头文件。确实,此功能可以迅速发挥作用并按预期工作。
然后,我创建了另一个文件,因为如果我尝试在该文件中导入我的c ++代码,它将尝试像objective-c一样编译它,但效果不佳。我相信该文件将是此标头的实现,并且我被告知这将是导入我的c ++代码的安全地方。
还有 Bridging-Header.m
#ifndef Bridging_Header_h
#define Bridging_Header_h
#import "Bridging-Header.h"
#import "rectangle.hpp"
int …Run Code Online (Sandbox Code Playgroud) 我正在编写一个跨平台引擎来进行渲染.我正在尝试创建一个跨平台结构,它基本上管理一种绘制的几何体.
目标是有一个c ++类,它为分配给缓冲区的内存块保存一个void*,然后将该指针传递给MTLBuffer或Vulcan Buffer以用于渲染.因此,这个类的一个领域需要是一个缓冲区,但在跨平台意义上.
对于我的绘图的一部分,代码应该是这样的
func draw() {
CrossPlatformBuffers* buffs = // preset list
for (buffer in buffs {
PlatformSpecificEngine.drawWith((PlatformSpecificBuffer)buffs->buffer)
}
}
Run Code Online (Sandbox Code Playgroud)
所以基本上我需要能够将我的MTLBuffer存储为c ++类中的void*.这让我感到困惑,因为我不确定c ++如何使用objective-c ARC或者id应该是什么意思.
如果我只是将id转换为void*并将其传递到c ++类中,然后将其称为delete,我会遇到任何问题吗?
我有一个巨大的vbo,整个事情每一帧都在改变.
我听说过快速更改缓冲区数据的不同方法,但其中只有一个对我的程序来说是一个好主意.但是,我不理解它,无法找到任何代码示例.
我听说有人声称你应该用"null"作为数据调用glBufferData,然后用每帧填充真实数据.这是什么目的?这在代码中是什么样的?
这是完整的 shadertypes.h 文件。我将把它分解成我无法理解的部分。
#ifndef ShaderTypes_h
#define ShaderTypes_h
//Part 1 Compiler flags
#ifdef __METAL_VERSION__
#define NS_ENUM(_type, _name) enum _name : _type _name; enum _name : _type
#define NSInteger metal::int32_t
#else
#import <Foundation/Foundation.h>
#endif
#include <simd/simd.h>
//Part 2 buffer index
typedef NS_ENUM(NSInteger, BufferIndex)
{
BufferIndexMeshPositions = 0,
BufferIndexMeshGenerics = 1,
BufferIndexUniforms = 2
};
//Part 3 vertex attribute and position
typedef NS_ENUM(NSInteger, VertexAttribute)
{
VertexAttributePosition = 0,
VertexAttributeTexcoord = 1,
};
//Part 4 texture index color
typedef NS_ENUM(NSInteger, TextureIndex)
{
TextureIndexColor = …Run Code Online (Sandbox Code Playgroud) 所以我在手机上设置了一个简单的模拟.目标是在屏幕上显示带有各种透明度的红色,白色和蓝色圆圈.我有大部分工作,除了一件事,而透明度的工作,唯一的混合发生在黑色背景.结果,中心的圆圈显示为深红色,而不是在其下方显示白色圆圈.我究竟做错了什么?
注意我正在使用正交2d投影矩阵.所有对象z位置都相同,并以特定顺序呈现.
以下是我如何设置透明度的方法:
glEnable(GLenum(GL_DEPTH_TEST))
glEnable(GLenum(GL_POINT_SIZE));
glEnable(GLenum(GL_BLEND))
glBlendFunc(GLenum(GL_SRC_ALPHA), GLenum(GL_ONE_MINUS_SRC_ALPHA))
glEnable(GLenum(GL_POINT_SMOOTH))
//Note some of these things aren't compatible with OpenGL-es but they can hurt right?
Run Code Online (Sandbox Code Playgroud)
这是片段着色器:
precision mediump float;
varying vec4 outColor;
varying vec3 center;
varying float o_width;
varying float o_height;
varying float o_pointSize;
void main()
{
vec4 fc = gl_FragCoord;
vec3 fp = vec3(fc);
vec2 circCoord = 2.0 * gl_PointCoord - 1.0;
if (dot(circCoord, circCoord) > 1.0) {
discard;
}
gl_FragColor = outColor;//colorOut;
}
Run Code Online (Sandbox Code Playgroud)
以下是我将每个圆圈传递给着色器的方法:
func drawParticle(part: Particle,color_loc: GLint, size_loc: GLint) …Run Code Online (Sandbox Code Playgroud) 我试图通过计算每个像素的所有 RGB 和 A 分量的总和来确定 MTLTexture(bgra8Unorm 格式)是否为空白。
此函数旨在通过在将纹理复制到指针后在内存中添加相邻的浮点数来实现此目的。但是我已经确定,无论给定的 MTLTexture,这个函数最终都会返回 false。
这个功能有什么问题?
func anythingHere(_ texture: MTLTexture) -> Bool {
let width = texture.width
let height = texture.height
let bytesPerRow = width * 4
let data = UnsafeMutableRawPointer.allocate(bytes: bytesPerRow * height, alignedTo: 4)
defer {
data.deallocate(bytes: bytesPerRow * height, alignedTo: 4)
}
let region = MTLRegionMake2D(0, 0, width, height)
texture.getBytes(data, bytesPerRow: bytesPerRow, from: region, mipmapLevel: 0)
var bind = data.assumingMemoryBound(to: UInt8.self)
var sum:UInt8 = 0;
for i in 0..<width*height {
sum += …Run Code Online (Sandbox Code Playgroud) 我对 Objective-c 很陌生,所以请耐心等待,我仍在尝试理解可以在目标 c 中放置属性和类变量的众多位置。
我是一名经验丰富的 Metal 开发人员,但我几乎没有用 Objective-c 做过任何事情。
我正在尝试创建一个 MetalCore 类,该类将保存 MTLDevice、MTLCommandQueue 并促进应用程序核心管道等的创建。
因此,我定义了以下内容
@property (readonly, nonatomic, assign) MTLDevice* devicePtr;
Run Code Online (Sandbox Code Playgroud)
然而,在我的课堂上,Unknown type name MTLDevice; did you mean...即使我得到了错误#import <Metal/Metal.h>,这里发生了什么?
我查看了堆栈溢出并找到了人们定义这样的函数的示例
- (<MTLDevice> *)device;
Run Code Online (Sandbox Code Playgroud)
或者
- (instancetype)initWithDevice:(id<MTLDevice>) device;
Run Code Online (Sandbox Code Playgroud)
整个 id 和 <> 是怎么回事?在什么情况下可以省略 id 部分?
我觉得特别奇怪的是,虽然大多数 Metal 类型似乎都需要 id,但有些类似的MTLRenderPipelineDescriptor不需要它,实际上只在该Type*模式下工作。这是为什么,我如何从文档中确定需要什么?
我遇到了一些c ++链表实现的代码.
struct node
{
int info;
struct node *next;
}*start;
Run Code Online (Sandbox Code Playgroud)
这意味着什么*start而不仅仅是start??
以后像这样使用会发生什么?什么s意思是它没有被函数中的任何其他地方引用?
struct node *temp, *s;
temp = new(struct node);
Run Code Online (Sandbox Code Playgroud) 我试图创建一个永远不会重复的类,因为它的字段中有很多数据.为此,我定义了这样的类:
class Foo {
public:
Foo(int i);
Foo();
Foo(const Foo&) = delete;
}
Run Code Online (Sandbox Code Playgroud)
如果我尝试执行以下操作,这会导致编译器错误:
Foo a(2);
Foo b = a;
Run Code Online (Sandbox Code Playgroud)
但无论出于何种原因,这都不包括复制数据的情况.
Foo* array;
array = new Foo[10000];
Foo a(2);
array[1] = a;
Run Code Online (Sandbox Code Playgroud)
为什么是这样?