在纹理的SceneKit绘画与纹理坐标 [英] SceneKit painting on texture with texture coordinates

查看:405
本文介绍了在纹理的SceneKit绘画与纹理坐标的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Collada模型,我加载到SceneKit中。当我在模型上执行hittest时,我能够检索被击中的模型的纹理坐标。

I have a Collada model that I load into SceneKit. When I perform a hittest on the model I am able to retrieve the texture coordinates of the model that was hit.

使用这些纹理坐标,我应该能够替换纹理坐标有颜色。
所以这样我就可以在模型上画画

With these texture coordinates I should be able to replace texture coordinates with a color. So this way I should be able to draw on the model

如果我错了,请纠正我。

Correct me if I am wrong so far.

到目前为止,我读了很多文章,但我没有让我的着色器正确。
(虽然我确实得到了一些时髦的效果; - )

I read a lot of articles till now but I just don't get my shaders right. ( Though I did get some funky effects ;-)

我的顶点着色器:

precision highp float;

attribute vec4 position;
attribute vec2 textureCoordinate;
attribute vec2 aTexureCoordForColor; //coordinates from the hittest

uniform mat4 modelViewProjection;

varying vec2 aTexureCoordForColorVarying; // passing to the fragment shader here
varying vec2 texCoord;

void main(void) {
    // Pass along to the fragment shader
    texCoord = textureCoordinate;
    aTexureCoordForColorVarying = aTexureCoordForColor; //assigning here
    // output the projected position
    gl_Position = modelViewProjection * position;
}

我的片段着色器

precision highp float;

uniform sampler2D yourTexture;

uniform vec2 uResolution;
uniform int uTexureCoordsCount;

varying vec2 texCoord;
varying vec2 aTexureCoordForColorVarying;

void main(void) {

    // ??????????? no idea anymore what to do here
    gl_FragColor = texture2D(yourTexture, texCoord);
}

如果您需要更多代码,请告诉我。

If you need more code please let me know.

推荐答案

首先,着色器不是绘制对象材质的唯一方法。另一个可能适合您的选项是使用SpriteKit场景作为素材内容 - 请参阅这个答案可以提供一些帮助。

First, shaders aren't the only way to draw onto an object's material. One other option that might work well for you is to use a SpriteKit scene as the material's contents — see this answer for some help with that.

如果你坚持着色器路线,你不需要重写整个着色器程序只是为了在现有纹理上绘制。 (如果你这样做,你会丢失SceneKit程序为你提供的东西,比如照明和凹凸贴图。除非你真的想要,否则重新发明这些轮子。)相反,使用着色器修饰符 - 一小段GLSL插入到SceneKit着色器程序。 SCNShadable参考介绍了如何使用这些参考资料。

If you stick to the shader route, you don't need to rewrite the whole shader program just to paint on top of the existing texture. (If you do, you lose things that SceneKit's program provides for you, like lighting and bump mapping. No sense reinventing those wheels unless you really want to.) Instead, use a shader modifier — a little snippet of GLSL that gets inserted into the SceneKit shader program. The SCNShadable reference explains how to use those.

第三,我不确定你是以最好的方式为着色器提供纹理坐标。您希望每个片段为点击的点获得相同的texcoord值,因此将它作为属性传递到GL并在顶点和片段阶段之间进行插值几乎没有意义。只需将其作为制服传递,并使用键值编码在材质上设置该制服。 (有关绑定着色器参数的信息,请参阅 SCNShadable参考)与KVC。)

Third, I'm not sure you're providing the texture coordinates to your shader in the best way. You want every fragment to get the same texcoord value for the clicked point, so there's little point to passing it into GL as an attribute and interpolating it between the vertex and fragment stages. Just pass it as a uniform, and set that uniform on your material with key-value coding. (See the SCNShadable reference again for info on binding shader parameters with KVC.)

最后,为了得到你问题的主要观点......:)

Finally, to get at the main point of your question... :)

要在特定纹理坐标集处或附近更改片段着色器(或着色器修改器)的输出颜色,只需将传入的单击坐标与用于常规纹理查找的当前texcoords集进行比较。以下是一个示例,执行着色器修改器路径:

To change the output color of the fragment shader (or shader modifier) at or near a particular set of texture coordinates, just compare your passed-in click coordinates to the current set of texcoords that'd be used for the regular texture lookup. Here's an example that does that, going the shader modifier route:

uniform vec2 clickTexcoord;
// set this from ObjC/Swift code with setValue:forKey:
// and an NSValue with CGPoint data

uniform float radius = 0.01; 
// change this to determine how large an area to highlight

uniform vec3 paintColor = vec4(0.0, 1.0, 0.0);
// nice and green; you can change this with KVC, too

#pragma body

if (distance(_surface.diffuseTexcoord.x, clickTexcoord.x) < radius) {
    _surface.diffuse.rgb = paintColor
}

将此示例用作 SCNShaderModifierEntryPointSurface 着色器修改器和灯光/阴影仍将应用于结果。如果您希望您的绘画覆盖光照,请使用 SCNShaderModifierEntryPointFragment 着色器修改器,并在GLSL代码段集 _output.color.rgb 而不是 _surface.color.rgb

Use this example as a SCNShaderModifierEntryPointSurface shader modifier and lighting/shading will still be applied to the result. If you want your paint to override lighting, use a SCNShaderModifierEntryPointFragment shader modifier instead, and in the GLSL snippet set _output.color.rgb instead of _surface.color.rgb.

这篇关于在纹理的SceneKit绘画与纹理坐标的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆