Draw centered circle - android

I'm trying to figure out how to draw a centered circle using fragment shader. I don't quite understand how to accomplish this. This is what I got so far, but the result is a white screen.
I want to be able to draw it any size and be able to change the offsets as I like (move the circle around).
void main()
{
float radius = 10.0;
float viewWidth = 340.0;
float viewHeight = 500.0;
float offsetX = viewWidth / 2.0;
float offsetY = viewHeight / 2.0;
float factorX = viewWidth / ( 360.0 / 6.3 );
float factorY = viewHeight / ( 360.0 / 6.3 );
float angleX = gl_FragCoord.x / factorX;
float angleY = gl_FragCoord.y / factorY;
float x = offsetX + ( sin( angleX ) * radius );
float y = offsetY + ( cos( angleY ) * radius );
float c = x + y;
gl_FragColor = vec4( c, c, c, 1.0 );
}

Remember, this program runs separately for each individual fragment. Each one need only decide if it's in or out of the circle. No need to use sin and cos here, just measure the distance from the center of the viewport, to see if the fragment is in the circle.
Here's a disc, which is even simpler: http://glslsandbox.com/e#28997.0
uniform vec2 resolution;
void main( void ) {
vec2 position = ( gl_FragCoord.xy / resolution.xy ) - 0.5;
position.x *= resolution.x / resolution.y;
float circle = 1.0 - smoothstep(0.2, 0.21, length(position));
gl_FragColor = vec4( vec3( circle ), 1.0 );
}
And here's a circle, made by tweaking the disc a little: http://glslsandbox.com/e#28997.1
uniform vec2 resolution;
void main( void ) {
vec2 position = ( gl_FragCoord.xy / resolution.xy ) - 0.5;
position.x *= resolution.x / resolution.y;
float circle = 1.0 - smoothstep(0.003, 0.005, abs(length(position) - 0.2));
gl_FragColor = vec4( vec3( circle ), 1.0 );
}

Related

Shader not rendering in Android export

My game uses gles 2 by Godot engine.
This shader displays stars with many little white dots. It works fine on the editor but it shows only the colour when exporting the project to android.
shader_type canvas_item;
uniform vec4 bg_color: hint_color;
float rand(vec2 st) {
return fract(sin(dot(st.xy, vec2(12.9898,78.233))) * 43758.5453123);
}
void fragment() {
float size = 100.0;
float prob = 0.9;
vec2 pos = floor(1.0 / size * FRAGCOORD.xy);
float color = 0.0;
float starValue = rand(pos);
if (starValue > prob)
{
vec2 center = size * pos + vec2(size, size) * 0.5;
float t = 0.9 + 0.2 * sin(TIME * 8.0 + (starValue - prob) / (1.0 - prob) * 45.0);
color = 1.0 - distance(FRAGCOORD.xy, center) / (0.5 * size);
color = color * t / (abs(FRAGCOORD.y - center.y)) * t / (abs(FRAGCOORD.x - center.x));
}
else if (rand(SCREEN_UV.xy / 20.0) > 0.996)
{
float r = rand(SCREEN_UV.xy);
color = r * (0.85 * sin(TIME * (r * 5.0) + 720.0 * r) + 0.95);
}
COLOR = vec4(vec3(color),1.0) + bg_color;
}
Any help please?

Rewriting an Android OpenGL filter to Metal (for CIFilter)

There are dozens of image filters written for the Android version of our app in GLSL (ES). As of iOS 12, OpenGL is deprecated, and CIFilter kernels have to be written in Metal.
I had some previous background in OpenGL, however writing CIFilter kernels in Metal is new to me.
Here is one of the filters. Could you help me in translating it to Metal as a CIFilter kernel? That would provide a good example for me so I could translate others.
#extension GL_OES_EGL_image_external : require
precision mediump float;
varying vec2 vTextureCoord;
uniform samplerExternalOES sTexture;
uniform float texelWidth;
uniform float texelHeight;
uniform float intensivity;
void main() {
float SIZE = 1.25 + (intensivity / 100.0)*2.0;
vec4 color;
float min = 1.0;
float max = 0.0;
float val = 0.0;
for (float x = -SIZE; x < SIZE; x++) {
for (float y = -SIZE; y < SIZE; y++) {
color = texture2D(sTexture, vTextureCoord + vec2(x * texelWidth, y * texelHeight));
val = (color.r + color.g + color.b) / 3.;
if (val > max) { max = val; } else if (val < min) { min = val; }
}
}
float range = 5. * (max - min);
gl_FragColor = vec4(pow(1. - range, SIZE * 1.5));
gl_FragColor = vec4((gl_FragColor.r + gl_FragColor.g + gl_FragColor.b) / 3. > 0.75 ? vec3(1.) : gl_FragColor.rgb, 1.);
}
Here's the Metal source for a kernel that attempts to replicate your described filter:
#include <metal_stdlib>
#include <CoreImage/CoreImage.h>
using namespace metal;
extern "C" {
namespace coreimage {
float4 sketch(sampler src, float texelWidth, float texelHeight, float intensity40) {
float size = 1.25f + (intensity40 / 100.0f) * 2.0f;
float minVal = 1.0f;
float maxVal = 0.0f;
for (float x = -size; x < size; ++x) {
for (float y = -size; y < size; ++y) {
float4 color = src.sample(src.coord() + float2(x * texelWidth, y * texelHeight));
float val = (color.r + color.g + color.b) / 3.0f;
if (val > maxVal) {
maxVal = val;
} else if (val < minVal) {
minVal = val;
}
}
}
float range = 5.0f * (maxVal - minVal);
float4 outColor(pow(1.0f - range, size * 1.5f));
outColor = float4((outColor.r + outColor.g + outColor.b) / 3.0f > 0.75f ? float3(1.0f) : outColor.rgb, 1.0f);
return outColor;
}
}
}
I assume you're already familiar with the basics of how to correctly build Metal shaders into a library that can be loaded by Core Image.
You can instantiate your kernel at runtime by loading the default Metal library and requesting the "sketch" function (the name is arbitrary, so long as it matches the kernel source):
NSURL *libraryURL = [NSBundle.mainBundle URLForResource:#"default" withExtension:#"metallib"];
NSData *libraryData = [NSData dataWithContentsOfURL:libraryURL];
NSError *error;
CIKernel *kernel = [CIKernel kernelWithFunctionName:#"sketch" fromMetalLibraryData:libraryData error:&error];
You can then apply this kernel to an image by wrapping it in your own CIFilter subclass, or just invoke it directly:
CIImage *outputImage = [kernel applyWithExtent:CGRectMake(0, 0, width, height)
roiCallback:^CGRect(int index, CGRect destRect)
{ return destRect; }
arguments:#[inputImage, #(1.0f/width), #(1.0f/height), #(60.0f)]];
I've tried to select sensible defaults for each of the arguments (the first of which should be an instance of CIImage), but of course these can be adjusted to taste.

How can I make quarter indicators in Android Wear Watch Face?

It's no secret. My math skills aren't that impressive.
I'm developing my own Wear Watchface. But I want to draw a Drawline to the center of the screen for every 10 minute place on the watch. (See the 500px analog example).
By using the Google example code I can achieve this but only an entire line from the side of the screen to the center. But I want it to be like 5% (or a fixed amount of pixels) in length of that like in the 500px watchface. This is Google's code for drawing the second dial:
float centerX = width / 2f;
float centerY = height / 2f;
float secRot = mTime.second / 30f * (float) Math.PI;
float secLength = centerX - 20;
float secX = (float) Math.sin(secRot) * secLength;
float secY = (float) -Math.cos(secRot) * secLength;
canvas.drawLine(centerX, centerY, centerX + secX, centerY + secY, mHandPaint);
By changing the mTime.second I can draw from a specific second.
Found the solution, here's a snippet:
int teller_minuut_stip = 0; //Current minute
float secRot_stip = teller_minuut_stip / 30f * (float) Math.PI;
float secRot_stip_klein = teller_minuut_stip / 30f * (float) Math.PI;
float secLength_stip = centerX - 10;
float secX = (float) Math.sin(secRot_stip) * secLength_stip;
float secY = (float) -Math.cos(secRot_stip) * secLength_stip;
float secLength_stip_klein = centerX - 140;
float secX_klein = (float) Math.sin(secRot_stip_klein) * secLength_stip_klein;
float secY_klein = (float) -Math.cos(secRot_stip_klein) * secLength_stip_klein;
float eindpunt_x = centerX + secX;
float eindpunt_y = centerY + secY;
float lijn_x = eindpunt_x - secX_klein;
float lijn_y = eindpunt_y - secY_klein;
canvas.drawLine(eindpunt_x, eindpunt_y, lijn_x, lijn_y, datePaint_cirkel_kleurtien);

Opengl ES 2.0 ortho projection blank screen

i'm quite new to opengl , and I'm trying to display a square with opengl es 2.0 with an orthographics projection ( on android using c++ and ndk ) , but all I get is a blank screen.
If i don't use the projection matrix I can get the square but it's stretched depending on surface's aspect ratio.
I'm building the matrix with the following code ( referring to https://www.opengl.org/sdk/docs/man2/xhtml/glOrtho.xml ):
GLfloat projMat[16];
void ortho(float left, float right, float top, float bottom, float near, float far){
float tx = ((right+left)/(right-left))*-1;
float ty = ((top+bottom)/(top-bottom))*-1;
float tz = ((far+near)/(far-near))*-1;
projMat[0] = 2/right-left;
projMat[1] = 0.0f;
projMat[2] = 0.0f;
projMat[3] = 0.0f;
projMat[4] = 0.0f;
projMat[5] = 2/top-bottom;
projMat[6] = 0.0f;
projMat[7] = 0.0f;
projMat[8] = 0.0f;
projMat[9] = 0.0f;
projMat[10] = -2/far-near;
projMat[11] = 0.0f;
projMat[12] = tx;
projMat[13] = ty;
projMat[14] = tz;
projMat[15] = 1.0f; }
And i call this function with : ortho(0.0,width,0.0, height,-1.0,1.0); , where width and height are surface's width and height.
My vertex shader :
attribute vec4 vPosition;
uniform mat4 projMatrix;
void main() {
gl_Position = projMatrix * vPosition;
};
My fragment shader :
precision mediump float;
void main() {
gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
}
And my draw function :
// 3D drawing
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(mProgram);
glUniformMatrix4fv(mPerspectivehandler, 1, GL_FALSE, projMat);
glEnableVertexAttribArray(mvPositionHandle);
glVertexAttribPointer(mvPositionHandle, 3, GL_FLOAT, GL_FALSE, 0, quadverts);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glDisableVertexAttribArray(mvPositionHandle);
Do you know where's the mistake?
Edit :
I added parentheses as suggested, but it still doesn't work
GLfloat projMat[16];
void ortho(float left, float right, float top, float bottom, float near, float far){
float tx = ((right+left)/(right-left))*-1;
float ty = ((top+bottom)/(top-bottom))*-1;
float tz = ((far+near)/(far-near))*-1;
projMat[0] = 2/(right-left);
projMat[1] = 0.0f;
projMat[2] = 0.0f;
projMat[3] = 0.0f;
projMat[4] = 0.0f;
projMat[5] = 2/(top-bottom);
projMat[6] = 0.0f;
projMat[7] = 0.0f;
projMat[8] = 0.0f;
projMat[9] = 0.0f;
projMat[10] = -2/(far-near);
projMat[11] = 0.0f;
projMat[12] = tx;
projMat[13] = ty;
projMat[14] = tz;
projMat[15] = 1.0f; }
You're missing parentheses in the matrix calculation for the diagonal elements. They should be:
projMat[0] = 2.0f / (right - left);
projMat[5] = 2.0f / (top - bottom);
projMat[10] = -2.0f / (far - near);
It can be hard to debug issues where nothing is rendered. You should simplify until you can isolate what is going wrong.
You've declared vPosition as a vec4, but in your comment, your vertex position array only has 12 floats (3 per vertex). a vec4 needs 4 floats per vertex. this is also a problem here:
glVertexAttribPointer(mvPositionHandle, 3, GL_FLOAT, GL_FALSE, 0, quadverts);
You use 3 as the second parameter in the line above, but vec4 in your shader means use 4 here. Be sure that quadVerts holds 4 floats per vertex!
To debug, don't use a projection matrix - just render your geometry directly to clip-coordinates in your shader like so:
attribute vec4 vPosition;
uniform mat4 projMatrix;
void main() {
gl_Position = vPosition;
};
If the above shader renders (after you fix your vec4 problem), then you can start to debug your projection matrix.
Does your glClear() call actually take effect? try changing the color with glClearColor() and make sure the background color changes accordingly. If it doesn't, you might have set up your GL window incorrectly.
This question is 4 months old and I don't know if you still need an aswer.
I also had a lot of problems with orto projection matrices in OpenGL, but this works (for me):
result[0] = 2.0 / (right - left);
result[1] = 0.0;
result[2] = 0.0;
result[3] = 0.0;
result[4] = 0.0;
result[5] = 2.0 / (top - bottom);
result[6] = 0.0;
result[7] = 0.0;
result[8] = 0.0;
result[9] = 0.0;
result[10] = (1.0f / (near - far));
result[11] = 0.0;
result[12] = ((left + right) / (left - right));
result[13] = ((top + bottom) / (bottom - top));
result[14] = (near / (near - far));
result[15] = 1;

Color overlay in android NDK

I want to implement the Hue/color/saturation color overlays.
I saw the macros:
#define ColorBlend_Saturation(T,A,B) ColorBlend_Hls(T,A,B,HueA,LuminationA,SaturationB)
I am trying to reproduce it in Adobe Photoshop with colors #332244 and #557711 to get the result color - #431076. However, after applying these macros I get color - #320C59 as the result.
question 1: how can I reproduce the photoshop algorithms for hue, saturation and color?
question 2: how can I adjust the alpha channel? for example, on my colors and optically == 50, this should be in photoshop - #3b195d
question 1:
Photoshop’s hue, saturation, color, and luminosity blend modes are based on a color space with dimensions that the article HSL and HSV calls hue, chroma, and luma. Note that this space is different from both HSL and HSV, and only the hue dimension is shared between the three; see that article for details.
The Hue blend mode preserves the luma and chroma of the bottom layer, while adopting the hue of the top layer.
The Saturation blend mode preserves the luma and hue of the bottom layer, while adopting the chroma of the top layer.
The Color blend mode preserves the luma of the bottom layer, while adopting the hue and chroma of the top layer.
from http://en.wikipedia.org/wiki/Blend_modes
After more than 3 hours of experimenting i succeded to upgrade HSV -> RGB converter to working saturation blender. Other Blending modes should be simmilar.
Here is code:
#include <cmath>
#include <iostream>
using namespace std;
struct HSVColor
{
float H,S,V;
};
struct RGBColor
{
float R,G,B;
RGBColor() = default;
RGBColor(int r,int g, int b):
R(r/255.0),
G(g/255.0),
B(b/255.0)
{
}
};
HSVColor RGBToHSV(const RGBColor& RGB)
{
float Max;
float Min;
float Chroma;
HSVColor HSV;
Min = min(min(RGB.R, RGB.G), RGB.B);
Max = max(max(RGB.R, RGB.G), RGB.B);
Chroma = Max - Min;
//If Chroma is 0, then S is 0 by definition, and H is undefined but 0 by convention.
if(Chroma != 0)
{
if(RGB.R == Max)
{
HSV.H = (RGB.G - RGB.B) / Chroma;
if(HSV.H < 0.0)
{
HSV.H += 6.0;
}
}
else if(RGB.G == Max)
{
HSV.H = ((RGB.B - RGB.R) / Chroma) + 2.0;
}
else //RGB.B == Max
{
HSV.H = ((RGB.R - RGB.G) / Chroma) + 4.0;
}
HSV.H *= 60.0;
HSV.S = Chroma / Max;
}
HSV.V = Max;
return HSV;
}
RGBColor Saturate(const HSVColor& HSV,const HSVColor& overlay)
{
float os = overlay.S;
float ov = overlay.V;
float Min;
float Chroma;
float Hdash;
float X;
RGBColor RGB{0,0,0};
Chroma = os * ov; // Orginal was HSV.S * HSV.V
Hdash = HSV.H / 60.0;
X = Chroma * (1.0 - abs(fmod(Hdash , 2.0) - 1.0));
if(Hdash < 1.0)
{
RGB.R = Chroma;
RGB.G = X;
}
else if(Hdash < 2.0)
{
RGB.R = X;
RGB.G = Chroma;
}
else if(Hdash < 3.0)
{
RGB.G = Chroma;
RGB.B = X;
}
else if(Hdash < 4.0)
{
RGB.G= X;
RGB.B = Chroma;
}
else if(Hdash < 5.0)
{
RGB.R = X;
RGB.B = Chroma;
}
else if(Hdash <= 6.0)
{
RGB.R = Chroma;
RGB.B = X;
}
Min = ov - Chroma; // Orginal was HSV.V - Chroma
RGB.R += Min;
RGB.G += Min;
RGB.B += Min;
return RGB;
}
int main(){
RGBColor base{51, 34, 68};
RGBColor overly{85, 119, 17};
RGBColor r = Saturate(RGBToHSV(base),RGBToHSV(overly));
cout << int(r.R*255) << endl;
cout << int(r.G*255) << endl;
cout << int(r.B*255) << endl;
}
original HSV <-> RGB converter code here: http://wiki.beyondunreal.com/HSV-RGB_Conversion
question 2.
With Saturation this is actually easy, After saturation blending use normal alpha blending in rgb color space.
RGBColor base;
RGBColor overly;
RGBColor saturated = Saturate(base,overly);
RGBColor result = AlphaBlend(base,saturated,overly.alpha);
Note: this may not work with other blending modes.
Here are equations for different Photoshop blending modes:
inline float Blend_Normal( float Base, float Overlay )
{
return Base;
}
inline float Blend_Lighten( float Base, float Overlay )
{
return ( Overlay > Base ) ? Overlay : Base;
}
inline float Blend_Darken( float Base, float Overlay )
{
return ( Overlay > Base ) ? Base : Overlay;
}
inline float Blend_Multiply( float Base, float Overlay )
{
return Base * Overlay;
}
inline float Blend_Average( float Base, float Overlay )
{
return ( Base + Overlay ) / 2.0f;
}
inline float Blend_Add( float Base, float Overlay )
{
return LMin( Base + Overlay, 1.0f );
}
inline float Blend_Subtract( float Base, float Overlay )
{
return LMax( Base + Overlay - 1.0f, 0.0f );
}
inline float Blend_Difference( float Base, float Overlay )
{
return fabs( Base - Overlay );
}
inline float Blend_Negation( float Base, float Overlay )
{
return 1.0f - fabs( 1.0f - Base - Overlay );
}
inline float Blend_Screen( float Base, float Overlay )
{
return 1.0f - ( 1.0f - Base ) * ( 1.0f - Overlay );
}
inline float Blend_Exclusion( float Base, float Overlay )
{
return Base + Overlay - 2 * Base * Overlay;
}
inline float Blend_Overlay( float Base, float Overlay )
{
return ( Overlay < 0.5f ) ? ( 2.0f * Base * Overlay ) : ( 2.0f * Base - 1.0f ) * ( 1.0f - Overlay );
}
inline float Blend_SoftLight( float Base, float Overlay )
{
return ( Overlay < 0.5f ) ? ( Base + 0.5f ) * Overlay : ( Base - 0.5f ) * ( 1.0f - Overlay );
}
inline float Blend_HardLight( float Base, float Overlay )
{
return Blend_Overlay( Overlay, Base );
}
inline float Blend_ColorDodge( float Base, float Overlay )
{
return ( Overlay > 1.0f - Math::EPSILON ) ? Overlay : LMin( 1.0f, Base / ( 1.0f - Overlay ) );
}
inline float Blend_ColorBurn( float Base, float Overlay )
{
return ( Overlay < Math::EPSILON ) ? Overlay : LMax( 0.0f, 1.0f - ( 1.0f - Base ) / Overlay );
}
inline float Blend_LinearDodge( float Base, float Overlay )
{
return Blend_Add( Base, Overlay );
}
inline float Blend_LinearBurn( float Base, float Overlay )
{
return Blend_Subtract( Base, Overlay );
}
inline float Blend_LinearLight( float Base, float Overlay )
{
return ( Overlay < 0.5f ) ? Blend_LinearBurn( Base, 2 * Overlay ) : Blend_LinearDodge( Base, ( 2 * ( Overlay - 0.5f ) ) );
}
inline float Blend_VividLight( float Base, float Overlay )
{
return ( Overlay < 0.5f ) ? Blend_ColorBurn( Base, 2 * Overlay ) : Blend_ColorDodge( Base, ( 2 * ( Overlay - 0.5f ) ) );
}
inline float Blend_PinLight( float Base, float Overlay )
{
return ( Overlay < 0.5f ) ? Blend_Darken( Base, 2 * Overlay ) : Blend_Lighten( Base, ( 2 * ( Overlay - 0.5f ) ) );
}
inline float Blend_HardMix( float Base, float Overlay )
{
return ( Blend_VividLight( Base, Overlay ) < 0.5f ) ? 0.0f : 1.0f;
}
inline float Blend_Reflect( float Base, float Overlay )
{
return ( Overlay > 1.0f - Math::EPSILON ) ? Overlay : LMin( 1.0f, Base * Base / ( 1.0f - Overlay ) );
}
inline float Blend_Glow( float Base, float Overlay )
{
return Blend_Reflect( Overlay, Base );
}
inline float Blend_Phoenix( float Base, float Overlay )
{
return LMin( Base, Overlay ) - LMax( Base, Overlay ) + 1.0f;
}
From Linderdaum Engine SDK.

Categories

Resources