Я написал шейдер треугольника с функцией края и попытался использовать вес для его раскрашивания, но по какой-то причине цвета разделились на 4 отдельных треугольника, каждый со своей уменьшенной версией шейдера. функция рисования представляет собой всего две строки кода для цвета и положения и не должна вызывать эту ошибку.
int edgeFunction(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t x3, uint16_t y3){
return (x2-x1)*(y3-y1)-(y2-y1)*(x3-x1);
}
std::vector<fragment> RGBtri(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t x3, uint16_t y3){
std::vector<fragment> tri; //fragment is a struct with xyrgba
int minX = std::min(x1, std::min(x2,x3));
int maxX = std::max(x1, std::max(x2,x3));
int minY = std::min(y1, std::min(y2,y3));
int maxY = std::max(y1, std::max(y2,y3));
int p = edgeFunction(x1,y2,x2,y2,x3,y3);
for(uint16_t y = minY;y<=maxY;y++){
for(uint16_t x = minX;x<=maxX;x++){
int a = edgeFunction(x2,y2,x3,y3,x,y);
int b = edgeFunction(x3,y3,x1,y1,x,y);
int c = edgeFunction(x1,y1,x2,y2,x,y);
if ((a|b|c)>=0){
float d = ((float)a*255/(float)p);
float e = ((float)b*255/(float)p);
float f = ((float)c*255/(float)p);
uint8_t r = static_cast<uint8_t>(d);
uint8_t g = static_cast<uint8_t>(e);
uint8_t b = static_cast<uint8_t>(f);
tri.push_back({x,y,r,g,b,255});
}
}
}
return tri;
}
Много информации я получила здесь
Я попробовал несколько вариантов, но в большинстве случаев мне удалось поменять местами разделы rgb и cmy.
моя цель - иметь красный, зеленый и синий цвета в вершинах основного треугольника, а не разделять
@MikeVine Это проверка того, все ли переменные положительны, и если все они положительны, то точка находится внутри треугольника и помещается в вектор с цветом
о лол, ок... Думаю, это сработает, но это определенно выглядит очень странно. Почему бы просто не написать это как обычно и позволить компилятору делать некоторые трюки :)
@MikeVine Я читал, что так будет быстрее, вы правы насчет того, что компилятор делает это за кулисами, | объединяя их вместе и проверяя каждый из них по отдельности, создаются одни и те же инструкции по сборке с включенной оптимизацией O3.
Компиляторы пишут люди (на данный момент), и люди пишут правила оптимизации, используемые компиляторами, на основе того, что люди понимают. В большинстве случаев компилятор оптимизирует совершенно глупый, легко распознаваемый и интерпретируемый код, чтобы он был лучше, чем тот хитрый код, который вы оптимизировали вручную. Во-первых, часто рассматриваются целые блоки кода, а не отдельные строки. Общее эмпирическое правило заключается в том, чтобы писать код настолько глупым, насколько это возможно, позволить компилятору его попробовать и делать что-то странное только после того, как вы профилировали вывод компилятора и обнаружили, что он не нужен.
Нашел ответ, точка p равна x1 y2 для первой точки, а не x1 y1, abc не следует умножать на 255, результат следует умножить на 255, а затем привести к uint8
std::vector<fragment> RGBtri(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t x3, uint16_t y3){
std::vector<fragment> tri;
int minX = std::min(x1, std::min(x2,x3));
int maxX = std::max(x1, std::max(x2,x3));
int minY = std::min(y1, std::min(y2,y3));
int maxY = std::max(y1, std::max(y2,y3));
int p = edgeFunction(x1,y1,x2,y2,x3,y3);
for(uint16_t y = minY;y<=maxY;y++){
for(uint16_t x = minX;x<=maxX;x++){
int a = edgeFunction(x2,y2,x3,y3,x,y);
int b = edgeFunction(x3,y3,x1,y1,x,y);
int c = edgeFunction(x1,y1,x2,y2,x,y);
if (a>=0&&b>=0&&c>=0){
float w1 = ((float)a/(float)p);
float w2 = ((float)b/(float)p);
float w3 = ((float)c/(float)p);
uint8_t R = red.r*w1+green.r*w2+blue.r*w3;
uint8_t G = red.g*w1+green.g*w2+blue.g*w3;
uint8_t B = red.b*w1+green.b*w2+blue.b*w3;
tri.push_back({x,y,R,G,B,255});
}
}
}
return tri;
}
if ((a|b|c)>=0)
Я на 99% уверен, что это неправильно. Что вы подразумеваете под этой строкой?