I'm trying to implement a shader that can round the corners of a texture, and apply a border around it. This would be used in a window manager to have rounded windows with borders around them. The current fragment shader is as shown below (pardon the formatting).
const GLchar surface_fragment_src_rgba[] =
"precision mediump float;\n"
"varying vec2 v_texcoord;\n"
"uniform sampler2D tex;\n"
"\n"
"uniform vec2 half_size;\n"
"uniform vec2 position;\n"
"uniform float alpha;\n"
"uniform float radius;\n"
"uniform float half_border_thickness;\n"
"uniform vec4 border_color;\n"
"\n"
"float RectSDF(vec2 p, vec2 b, float r) {\n"
" vec2 d = abs(p) - b + vec2(r);\n"
" return min(max(d.x, d.y), 0.0) + length(max(d, 0.0)) - r;\n"
"}\n"
"\n"
"void main() {\n"
" vec2 center = gl_FragCoord.xy - position - half_size;\n"
" float dist = RectSDF(center, half_size + half_border_thickness, radius - half_border_thickness);\n"
"\n"
" vec4 tex_color = texture2D(tex, v_texcoord) * alpha;\n"
" vec4 from_color = border_color;\n"
" vec4 to_color = vec4(0.0);\n"
" if (half_border_thickness > 0.0) {\n"
" if (dist < 0.0) {\n"
" to_color = tex_color;\n"
" }\n"
" dist = abs(dist) - half_border_thickness;\n"
" } else {\n"
" from_color = tex_color;\n"
" }\n"
"\n"
" float blend_amount = smoothstep(-1.0, 1.0, dist);\n"
" gl_FragColor = mix(from_color, to_color, blend_amount);\n"
"}\n";
I have a mockup on shadertoy.
I am pretty confident that the shader works as intended, but my problem is that the shader doesn't operate outside of the original bounds of the texture. As an example, this is what it looks like when rendering a window. If anyone knows how I can render the region of the window plus the borders please let me know!
As a side note, if this is a suboptimal way to go about this, please let me know :) Originally, I rendered borders with a separate shader, but I figured I'd need knowledge of the texture's colors to blend the borders for antialiased rounded corners.
Related
I am trying to achieve a slanted divider effect with WebGL. The desired outcome is something like a view with 1 interactive divider (slanted) at the middle that allows the user to drag and view a mountain terrain with different colours.
The effect should look like this: slanted draggable divider
I have experimented based on a few examples I found online, but both methods used THREE.WebGLRenderer.setScissor() for the effect, and the results are rectangles.
May I know what are the alternatives to achieve the effect? Stencil buffer and masking? Better THREE.Camera setup? glViewport?
I have tried using react-three/drei's View and changing the CSS clip-path property, but it seems to stay rectangular.
Examples:
https://threejs.org/examples/webgl_multiple_scenes_comparison
https://codepen.io/sunnysideup8888/pen/poVvyvR
SetScissor implementation in the examples:
renderer.setScissor(0, 0, splitPos, sizes.height);
renderer.render(sceneL, camera);
renderer.setScissor(splitPos, 0, sizes.width, sizes.height);
renderer.render(sceneR, camera);
I textured an object in Blender because it wouldn't texture properly in Unity, and then imported the object and texture to Unity.
I don't know how to fix this, I'll put both pictures here.
Blender Texture Before Import
Object In Unity
Okay, so based on your screenshots..
You're going to select everything then add a modifier called "Solidify", then set this to something very small like .03. (Unity doesn't like objects that are just planes).
double check all your normals are facing out. Let me know if you don't know how to do this...
Go into edit mode select all edges, then right click, select "mark as seam".
Open UV editor window (should be split screen with Edit mode on one side, UV view on the other). In the Edit side select all, then go to UV dropdown menu and click "unwrap". You should then see your object unfolded into flat planes over on the UV window side. There's different unwrap options, like smart UV unwrap, etc. I think just "unwrap" has worked for me, but play around and there may be something that shows your object shapes in a less distorted way..
At this point, since your pattern is basically repeating. If you export the OBJ file and take it into unity, and you add the image file (make sure it's dimensions are perfectly square) it should receive the image file as an Albedo texture much better than in your screenshots. You can play with the 'tiling' and "X/Y offset" till it looks right (you might face issues with rotation though.
BUT
If you want to line it up very specifically, you can export the UV layout as a png from the UV window in blender. Then use photoshop or another photo editor to change/rotate and arrange your texture so the sides line up properly. In blender in the Edit window (assuming you still have both UV + editor open) when you select a side it will highlight in the UV window the corresponding flat plane, based on this you should be able to figure out what should be rotated up/down, etc. Then when you change that 2d image and drag it into Unity, it will adjust and wrap around the object.
I'm pretty new to both, but the advice I've been given is to not do the texturing in blender, but instead to do it in Unity.
This is a 10-month-old post but incase anyone is curious or struggling the same, Blender exports models with a scale of 100 so you need to scale up the tile of the material (in material settings) to see it.
This is a bad solution however because then you are not working with objects on a scale of 1 so you actually want to check "Apply transformations" when exporting the FBX model in blender
I want to render all the vertexes and the lines in the mesh.
I tried
1) A custom shader following this link
https://github.com/mrdoob/three.js/issues/2028
2) Set transparency with the material or like:
THREE.MeshNormalMaterial( { transparent: true, opacity: 0.5 } ),
3) Set ink material to the model in 3dMax and export to an obj file and load it in Threejs with objloader
None of them works fine.
Is there any solution to load mashes from 3dMax model (using objloader) and apply it with ink material in Threejs, just like what we can do in 3DMax?
See below as an example
http://makeitcg.com/wireframe-rendering-techniques-in-3ds-max/160/
First of all, Number 3) will NEVER work with OBJ, because obj will not export the ink shader from 3dsMax. And just to be clear, i don't think there is ANY way you can export the 3dsMax Shader.
Then, I don't understand what 2) is about. What do you want to achieve anyway? Do you want to set an object to be transparent? What does this have to do with Ink 'n Paint? Btw. i am not sure if transparency works for MeshNormalMaterial, i guess it should but Lambert and Phong will definetly work with transparency.
The problem is that you do not state what you want to achieve. From 1) it seems you want an outline around an object. For an outline see this example: http://stemkoski.github.io/Three.js/Outline.html or this one as a more advanced example: http://stemkoski.blogspot.de/2013/07/shaders-in-threejs-glow-and-halo.html
If you want to set transparent objects, well try MeshLambert or meshBasic material if MeshNormal does not work (i am not sure Right Now and can't check)
3) if you want to have a Ink 'n Paint shader, you need a Custom Shader. See examples here:
http://www.chromeexperiments.com/detail/cel-shader/
and already done with three.js here:
http://learningthreejs.com/data/THREEx/docs/THREEx.CelShader.html
Just apply the shader, see examples for setting up a ShaderMaterial.
I'm working in webGL. I'm pretty new to OpenGL. Having trouble with the blending function. My options look like:
gl.enable(gl.BLEND)
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
I render a source rectangle with color [0,0,0,0.5] on top of a destination background with color [0,0,0,1]. Based on everything I've read, I expect the result to be black. Instead it looks to be about 25% white. Here's what I get when I render red and black rectangles with alpha values ranging from 0.0 to 1.0.
View live demo and source here. Am I misunderstanding the blending function, and if so, how do I get what I expect? Thanks!
You should specify separate function for alpha:
gl.enable(gl.BLEND);
gl.blendEquation(gl.FUNC_ADD);
gl.blendFuncSeparate(
gl.SRC_ALPHA,
gl.ONE_MINUS_SRC_ALPHA,
gl.ONE,
gl.ONE_MINUS_SRC_ALPHA
);
What i need is a bit difficult to explain. Let's try...
I need to write a text in my app, and that text will gradually change color from left to right.
I think i could say it's a similar effect to what you see in a karaoke screen.
For instance. I draw a text line, in blue color, and gradually, using a timer, the color from left to right changes to red. But i don't want it to change letter by letter, but gradually. That would require that at some moment, the same letter can have a part in red and a part in blue.
I've been reading about core drawing, and maybe it's the solution, but i really don't know how to start. I was thinking about using a background layer and in top of it draw a transparent text (only with border), but i am not very sure how to do it.
any ideas would be appreciated.
You can probably do the job with a CGLayer.
Best of all you should be able to use your existing code to draw the characters (or anything else) in to the CGLayer.
Here's some rough code:
// first, make a CGLayer...
CGLayerRef yourDrawingPad =
CGLayerCreateWithContext(UIGraphicsGetCurrentContext(),etc..
CGContextRef yourRef = CGLayerGetContext(yourDrawingPad);
// now, draw to yourRef .. draw your various typography (or anything)
// use your current drawing code.
// all done drawing, now make an image mask...
UIGraphicsBeginImageContext(CGLayerGetSize(yourDrawingPad));
CGContextRef temp = UIGraphicsGetCurrentContext();
CGContextDrawLayerAtPoint(temp, CGPointZero, yourDrawingPad);
CGImageRef anAlphaMask = CGBitmapContextCreateImage(temp);
UIGraphicsEndImageContext();
You now have a nice mask you can use:
CGContextSaveGState(UIGraphicsGetCurrentContext()) ...
CGContextClipToMask(UIGraphicsGetCurrentContext(), self.frame, anAlphaMask);
So just mask it in to an image of a gradient, or whatever works.
(Conceivably: perhaps you will have to construct a bitmap image offscreen, and then use that as the mask?)
Footnote: Don't forget it is very likely you will have to paint upside down! Fortunately that is simple to deal with. Where it says "now, draw to yourRef" before drawing save your state and add the two lines of code:
CGContextTranslateCTM(refForMask, 0, self.frame.size.height);
CGContextScaleCTM(refForMask, 1.0, -1.0);
Hope it helps
I have an idea of how this could be done, but it is kind of complex. You could create an NSBezierPath and add the glyphs for each character. Then, set that as the clip and draw a NSGradient. Then you would just have to change the offset of the colors in the NSGradient to move the color along.